Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QDialog, Qt::ApplicationModal, open() vs exec(),
QtWS25 Last Chance

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

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 7.5k Views
  • 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.
  • JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by
    #1

    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
    0
    • JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by JonB
      #2

      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
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        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

        JonBJ 1 Reply Last reply
        2
        • SGaistS SGaist

          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.

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by
          #4

          @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
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            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

            JonBJ 1 Reply Last reply
            1
            • SGaistS SGaist

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

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by
              #6

              @SGaist
              Ohhh, I see! Thanks :)

              1 Reply Last reply
              0
              • T Offline
                T Offline
                The_DarkKnighT
                wrote on last edited by
                #7

                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
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved