QDialog exec no longer modal after show
-
So the problem is that if have my own dialog such as
class DlgFoobar : public QDialog {... }
then let's say in my MainWindow I have the following
void MainWindow::something()
{
DlgFoobar dlg(this);dlg.show();
...
dlg.exec();
}Simsalabim.. the dialog is no longer modal. In other words the user can click on other controls in the mainwindow.
What gives?
Comments on exec()
So calling exec() without show() being called first works as expected. The dialog remains modal and the user is restricted to only applying input on the dialog.
The problem is that using exec() is not adequate.
Consider a case where you wish to restore the dialog state to a previous state, i.e. populate the dialog and its data in some meaningful way.
To do this with smooth UX you really need to:
- Load and restore the dialog geometry before showing!
- if you first show and then restore the resizing will cause ugly visual flicker and disturbance.
- Show it after the geometry has been restored
- Then load any other state, including state that might fail (for example imagine a file is no longer available)
3.1 You need to have the dialog open so that you can open a QMessageBox properly using the dialog as the window parent in order to open the msg box properly. - Finally call exec() and block the user to the dialog.
Is there a way to do this or is this yet again something that has to be hacked together to workaround qt issues?
Thanks!
- Load and restore the dialog geometry before showing!
-
Show() creates a modeless dialog. So don't use it when you want a modal one.
-
@Christian-Ehrlicher said in QDialog exec no longer modal after show:
Show() creates a modeless dialog. So don't use it when you want a modal one.
Uh uh, did you read why it's needed?
-
@SamiV123 Yes. Maybe you can convince the devs to change this behavior but I doubt it.
http://bugreports.qt.io -
@SamiV123
try this:class DlgMsg : public QDialog { public: DlgMsg() : QDialog(nullptr) {} void showMessage(const QString& str) { QTimer::singleShot(1000,this,[str,this]() { auto msg=QMessageBox(this); msg.setWindowModality(Qt::WindowModal); msg.setText(str); msg.exec(); }); } }; ... DlgMsg dmsg; dmsg.resize(400,200); dmsg.showMessage("Something wrong happened!"); dmsg.exec();
-
@SGaist said in QDialog exec no longer modal after show:
Check your dialog lifetime. If it's a function local object then it will be destroyed after calling open since it's the last method call in the function.
Doh, you're right, so open() returns immediately so of course that will that not work.
Actually open() seems very cumbersome to use, it's a lot easier to simply create the Dialog on the stack and call exec()