QDialog, Qt::ApplicationModal, open() vs exec(),
-
Qt 5.7. PyQt (should not be relevant). Ubuntu 17.04 with default Unity desktop (might or might not be relevant). Cannot test under Windows.
I'm playing around trying to understand if there is any significance to the inconsistent fact that the code I have inherited sometime uses
QDialog.exec()
and sometimes usesQDialog.open()
.I know that both set the dialog modal. I know that the difference is that
open()
allows my code to continue (if it wants to do anything) whileexec()
blocks. (I suspect in my code usage is random, in that it doesn't actually do anything afteropen()
, but not sure yet.)I thought
exec()
would just goopen()
and then enter a blocking loop, and that was it. However, read on....I am seeing some seemingly odd behaviour(?) from
open()
but notexec()
if I choose to setQt::ApplicationModal
.def btn1_on_clicked(self): dlg = QtWidgets.QDialog() dlg.setWindowTitle("Dialog") # Next line ensures we have a reference to dialog if we call dlg.open(), # so we don't have any "out-of-scope-reference" issue # but can be removed without affecting the behaviour below self.dlg = dlg print("Before setWindowModality is modal: ", dlg.isModal()) print("Before setWindowModality modality: ", dlg.windowModality()) dlg.setWindowModality(QtCore.Qt.ApplicationModal) print("Before open is modal: ", dlg.isModal()) print("Before open modality: ", dlg.windowModality()) dlg.exec() print("After open is modal: ", dlg.isModal()) print("After open modality: ", dlg.windowModality())
Run the above and I get:
Before setWindowModality is modal: False Before setWindowModality modality: 0 Before open is modal: True Before open modality: 2 After open is modal: True After open modality: 2
Hunky-dory. Now change
dlg.exec()
todlg.open()
. There is only one change, to the final line of output:After open modality: 1
So,
exec()
retains mysetWindowModality(QtCore.Qt.ApplicationModal)
, butopen()
alters it toQt::WindowModal
.Why??
Behaviour-wise:
- Since
open()
has change to window-modal, and no parent window was specified, there is no modality against the invoking window exec()
does block the invoking window. But as a separate observation: sometimes (mostly?) clicking on invoker causes nothing visual (good), but sometimes you see the back window come up-front and then the modal dialog comes back up-front a moment later (ugly). Nothing to do with where you click, probably more like a timing thing. Perhaps Windows is better at this but Linux desktop manager/X11 is not offering application-modality and so Qt has to kludge it itself?
- Since
-
Hi,
That's because
open
is not blocking, so you are printing the "current state", you should connect thefinished
signal and only print there the modality. You'll see it matches what's advertised. -
Hi,
That's because
open
is not blocking, so you are printing the "current state", you should connect thefinished
signal and only print there the modality. You'll see it matches what's advertised. -
By default open shows the dialog as window modal as explained in the slot documentation. Now what happens with your code is that open is called which means that the dialog will be shown as soon as possible (not immediately even if it feels like that) but between the moment open is called and the dialog is shown, the print statements will have been executed..
-
By default open shows the dialog as window modal as explained in the slot documentation. Now what happens with your code is that open is called which means that the dialog will be shown as soon as possible (not immediately even if it feels like that) but between the moment open is called and the dialog is shown, the print statements will have been executed..
-
Its just async behaviour with open()
From Qt's docs:
Avoid using this function; instead, use open(). Unlike exec(), open() is asynchronous, and does not spin an additional event loop. This prevents a series of dangerous bugs from happening (e.g. deleting the dialog's parent while the dialog is open via exec()). When using open() you can connect to the finished() signal of QDialog to be notified when the dialog is closed.