PDA

View Full Version : QDialog behavior changes when Qt::FramelessWindowHint is applied to it.



hickscorp
4th April 2012, 22:49
Hello,

i am facing a very weird problem. If i use Qt::FramelessWindowHint when constructing a QDialog, it's behavior is different than when i don't use the frameless flag. So far, i have noticed two major differences but i only have been able to workaround one.

1) The placement is not the same.
When calling ->show() on such QDialog-derived classes, the dialog isn't centered to it's parent QDialog. Instead, its top-left corner is being centered. So my workaround for this problem is to call move((this->width()-dlg->width())/2, (height()-dlg->height())/2); No big deal, but very weird.

2) The accept / reject messages are being "bubbled" to the parent dialog.
When such frameless dialog is shown, if i press the close button (Directly connected to the close() slot of the dialog), everything is fine. However, if i press ESC, the dialog gets discarded as expected, but the parent dialog too. i am looking for either a solution to this problem, or maybe to another way of making the dialog frameless.

Note that i'm using Qt OpenSource 4.8.0 on Windows, and it might be interesting to know if the issues are the same on linux / MacOS.

Thanks,
Pierre.

ChrisW67
5th April 2012, 05:40
It would help your cause if you posted a minimal, compilable code snippet that demonstrates the problem(s).

hickscorp
5th April 2012, 12:20
Hello,

Here it is.

#ifndef DlgTest_h
#define DlgTest_h

#include <QtCore/QDebug>
#include <QtGui/QDialog>
#include <QtGui/QPalette>
#include <QtGui/QTextEdit>
#include <QtGui/QPushButton>
#include <QtGui/QGridLayout>

class DlgTest : public QDialog {
Q_OBJECT
public:
/**/ DlgTest (quint32 num, QWidget *p=0, Qt::WFlags f=Qt::FramelessWindowHint|Qt::X11BypassWindowManag erHint)
: QDialog(p, f), _txt(0), _num(num) {
//setWindowFlags ();
if (_num>1)
setModal (true);
// Layout, button, and text box.
QGridLayout *grid = new QGridLayout(this);
QPushButton *btn = new QPushButton(this);
_txt = new QTextEdit(this);
_txt->setText (QString::number(_num));
grid->addWidget (_txt);
grid->addWidget (btn);
setLayout (grid);
// Upon clicking the button, launch another dialog.
connect(btn, SIGNAL(clicked()), this, SLOT(mainButtonClicked()));
};
protected slots:
void mainButtonClicked () {
DlgTest *dlg = new DlgTest(_num+1, this);
connect(dlg, SIGNAL(finished(int)), dlg, SLOT(deleteLater()));
dlg->show ();
qDebug() << dlg->geometry();
};
private:
QTextEdit *_txt;
quint32 _num;
};

#endif

You will start the first instance of this dialog with this in your main():


DlgTest dlg (1, (QWidget*)QApplication::desktop());
dlg.show();


Now, you will try the code with the flags that are in the constructor. Each new dialog will be offsetted.
After testing with these flags, you will replace "Qt::FramelessWindowHint|Qt::X11BypassWindowManager Hint" by 0, and try again.
The behavior i get with this minimal example isn't even the same as the one i have in my app... The offset being negative, in my app it's positive.
And the "ESC" problem isn't even here, so i guess it's related to something else i do in my app... i'll try to dig further.

Sorry for the indentation... Visual studio doesn't seem to understand what soft tabs are on this computer.


i found what to do to reproduce the ESC bug. Remove the flags from the constructor (Replace them by 0 by default). Then, put this in the constructor:

setWindowFlags(Qt::Dialog|Qt::FramelessWindowHint| Qt::X11BypassWindowManagerHint);
i have tried:

setWindowFlags(windowFlags()|Qt::FramelessWindowHi nt|Qt::X11BypassWindowManagerHint);
But the result is even different and unusable. So maybe i misunderstood the use of those flags?


Pierre.

Spitfire
9th April 2012, 10:43
Your dialog changes position because of sanity check in QDialog::adjustPosition().
Frameless windows will be offseted from their parent by (minus) 10x40px.

I would expect the linux to behave the same (I haven't checked it though).

As to the ESC issue - I couldn't reproduce it. Works fine for me no mater what I do (qt 4.6.3, w7).

If you're looking for a different way to make dialog 'frameless' then add this to your dialog (and get rid of all other flags):


void resizeEvent( QResizeEvent* )
{
this->setMask( QRegion( this->rect() ) );
}

hickscorp
9th April 2012, 11:54
Hello Spitfire, and thanks a lot for your help.

Your technique is very interesting, and i will try it.
As for the modals dialogs disappearing all at the same time when pressing ESC, i have found a workaround (Which is kind of ugly and forces me to keep track of windows orders, hide them, show them, etc so i can make the dialogs non-modal without risking to allow the user to change values in the parent windows).

If you are interested in reproducing the ESC bug, make my example dialog class modal (setModal(true)).

Thanks again!
Pierre.

Spitfire
9th April 2012, 12:48
I've tried both modal and non-modal dialogs and in both cases ESC acts as expected (unless you press and hold it).

I personally believe you're doing something wrong as this should not happen.
Are you handling events yourself somewhere?

I don't have Qt 4.8 to try at the moment but I don't think it's a Qt issue.

hickscorp
9th April 2012, 13:00
Hello again Spitfire!

i'm not handling events (The example i have posted reproduces the problem on my environment, Windows XP and Qt 4.8.0 compiled as dynamic).
i will try to make a small video showing the issue if i get a bit time to do so.

Thanks for your help,
Pierre.

Spitfire
10th April 2012, 12:16
I've tested your class on w7 qt 4.8.1 (vm) and everything works as expected.