Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
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 uses
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) while
exec()blocks. (I suspect in my code usage is random, in that it doesn't actually do anything after
open(), but not sure yet.)
exec()would just go
open()and then enter a blocking loop, and that was it. However, read on....
I am seeing some seemingly odd behaviour(?) from
exec()if I choose to set
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.open(). There is only one change, to the final line of output:
After open modality: 1
open()alters it to
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?
JonB last edited by JonB
Any comment from anyone on this one? So
exec()alters dialog from
Qt::WindowModal, but docs don't tell you this?
openis not blocking, so you are printing the "current state", you should connect the
finishedsignal and only print there the modality. You'll see it matches what's advertised.
Thanks for the reply. I can't say I understand (yes,
open()is non-modal, but what has that got to do with application vs parent window modality?). However I don't have a usage case at present so I'll just leave it.
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..
Ohhh, I see! Thanks :)
The_DarkKnighT last edited by
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.