Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved QDialog, Qt::ApplicationModal, open() vs exec(),

    General and Desktop
    3
    7
    5378
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • JonB
      JonB last edited by

      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 QDialog.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) 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.)

      I thought 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 open() but not exec() if I choose to set Qt::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() to dlg.open(). There is only one change, to the final line of output:

      After open modality:  1
      

      So, exec() retains my setWindowModality(QtCore.Qt.ApplicationModal), but open() alters it to Qt::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?
      1 Reply Last reply Reply Quote 0
      • JonB
        JonB last edited by JonB

        Any comment from anyone on this one? So QDialog.open() but not exec() alters dialog from QtCore.Qt.ApplicationModal to Qt::WindowModal, but docs don't tell you this?

        1 Reply Last reply Reply Quote 0
        • SGaist
          SGaist Lifetime Qt Champion last edited by

          Hi,

          That's because open is not blocking, so you are printing the "current state", you should connect the finished signal and only print there the modality. You'll see it matches what's advertised.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          JonB 1 Reply Last reply Reply Quote 2
          • JonB
            JonB @SGaist last edited by

            @SGaist
            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.

            1 Reply Last reply Reply Quote 0
            • SGaist
              SGaist Lifetime Qt Champion last edited by

              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..

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              JonB 1 Reply Last reply Reply Quote 1
              • JonB
                JonB @SGaist last edited by

                @SGaist
                Ohhh, I see! Thanks :)

                1 Reply Last reply Reply Quote 0
                • T
                  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.

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post