In the following code, I connect the triggered signals of QMenu.menuAction and QAction to similar slot functions. However, only the triggered signal of QAction is triggered. I am curious why this is?
menu = self.menuBar().addMenu("action_1")
menu.menuAction().triggered.connect(lambda: print("action_1"))
action = self.menuBar().addAction("action_2")
action.triggered.connect(lambda: print("action_2"))
The main purpose of the action returned from a QMenu menuAction()
is to add that action to another "action container".
The common cases are:
setDefaultAction()
, which will automatically show the menu related to that action, similarly (but not like) using setMenu()
;Leaving out the third case, which is a bit of an exception, the first two cases are "action containers" that show a list of actions.
Conceptually speaking, QMenuBar is similar to a persistent QMenu (see the documentation about using "tear-off" menus), for which some actions actually contain a sub menu: the menuAction()
is what is shown in the parent menu (or the menu bar).
Now, it's easy to get confused by the identical names of the triggered
signals available for QMenu and QAction. There is an important difference, though:
QMenu.triggered
: "This signal is emitted when an action in this menu is triggered"; QMenuBar has a similar signal as well that behaves identically;QAction.triggered
: "This signal is emitted when Considering all the above, the result is that:
trigger()
), only that action will emit the triggered
signal;triggered
signal with the action as its argument;When you click the action
named "action_2", you are only triggering that action, not the action of its parent menu. That's why you don't get the triggered
signal from the menuAction()
: the action associated with that menu has not being triggered (nor it should!).
The triggered
signal of the menu action of a QMenu is normally never used, and for obvious reasons: when the user clicks an item in a parent menu that refers to a sub menu (or a menu title in a menu bar) they usually want to just open that menu.
Finally, there are cases for which the triggered
signal of a menu action is used, and they're mostly used for advanced purposes: for instance, by creating a QMenu subclass that implements special calls (eg: when double clicking on a menu action of a submenu); those are very rare cases, though, normally implemented for special cases, done with high awareness of the Qt toolkit behavior and extended experience with it. Also, in those cases the triggered
signal has to be explicitly emitted, because Qt doesn't provide ways to automatically emit that, based on the assumption that there's no direct way to trigger the action related to a menu.