Nominate our 2022 Qt Champions!

[Solved]What’s the difference between QMenu.popup and QMenu.exec_

  • What’s the difference between
    PySide.QtGui.QMenu.popup(pos[, at=None])¶

    PySide.QtGui.QMenu.exec_(pos[, at=None])

    It would be great to explain it by By example 

    Although the documentation says

    Context menus are usually invoked by some special keyboard key or by right-clicking. They can be executed either asynchronously with PySide.QtGui.QMenu.popup() or synchronously with exec() .

    But I still don’t understand

  • I'm afraid I run PyQt rather than PySide, but the following example should map pretty well:

    from PyQt4.QtCore import *
    from PyQt4.QtGui import *

    class Widget(QWidget):
    def init(self, parent=None):
    QWidget.init(self, parent)

        self.popup=QRadioButton("Popup", checked=True)
    def showMenu(self, pos):
        menu.addAction(QAction("Item 1", menu))
        menu.addAction(QAction("Item 2", menu))
        menu.addAction(QAction("Item 3", menu))
        if self.popup.isChecked(): menu.popup(self.mapToGlobal(pos))
        else: menu.exec_(self.mapToGlobal(pos))
        print "Finished"

    if name=="main":
    from sys import argv, exit

    Basically, when you run this example you'll get two checkboxes: when "Popup" is checked the context menu will be invoked with popup() and when "Exec_" is checked the menu is invoked with exec_(). To actually invoke the menu, simply right click anywhere in the window.

    As to your actual question, the difference between popup() and exec_(): the answer was actually in your question, in that popup() is asynchronous and exec_() is synchronous. This means that when you use popup(), as soon as the menu is shown, execution of the application continues, as demonstrated by the fact that "finished" is printed into the terminal (almost) instantly. With exec_() however, "finished" is not printed into the terminal until the user either selects an action from the menu or clears it by clicking away/pressing esc. This is because exec_() blocks the main event loop and starts one of its own. This behavior is seen throughout Qt where widgets such as QDialog can either be displayed with show() or exec_().

    The upshot is, with popup() you use the signal/slot mechanism to determine which option the user picked (if any), i.e. the actions "triggered" signal will be fired which you connect to. With exec_(), the selected action is also returned by the function.

    Hope this helps.

  • From a user's point of view:

    In this case, word pairs with the same meaning:

    • asynch/synch
    • popup/exec
    • non-modal/modal

    Modal: when a thing ( dialog or in this case a menu) causes the GUI to enter a state where the user can do nothing else (other modes) in that app until the thing is finished.

    With some variations: if the user clicks outside a modal menu, it is finished and returns a null result. Whereas in a modal dialog, the user must click in a Cancel button to finish the dialog, and can't click elsewhere in your app with any effect.

    And even when an app is in a modal state, the user might be able to click in the windows of other apps (usually, it depends on the window manager, etc.)

    From a programmer's point of view, your app event loop doesn't receive events when a modal dialog or menu is displayed. (Qt does receive and handle events, but doesn't dispatch them to your event loop.)

Log in to reply