最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

qt - The difference between QMenu.menuAction and QAction in signal processing - Stack Overflow

programmeradmin0浏览0评论

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"))

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"))
Share Improve this question asked Mar 6 at 12:14 poisonpoison 254 bronze badges 4
  • 1 A QMenu does not represent an action, so its menuAction wll never be triggered. What are you actually trying to achieve? – ekhumoro Commented Mar 7 at 12:52
  • I read the source code of QT and found that when QMenuBar uses the addMenu(title: str) method to add a submenu, it first constructs a QMenu, and then calls addAction to add QMenu.menuAction to QMenuBar. So when I tried to use the triggered signal of the Action returned by menuAction, I found this difference. It aroused my curiosity. But my C++ level is very limited, and it is a challenge for me to continue reading the source code. So I asked this question. @ekhumoro – poison Commented Mar 8 at 3:15
  • @poison My answer should have covered enough about what you're asking, and probably even more. Please take your time to read it and do further research based on its contents. – musicamante Commented Mar 11 at 5:15
  • Thanks, @musicamante. I'm really sorry, I've read your answer. I think I understand part of it. I originally planned to refer to your answer and try to read the source code to understand the implementation logic. But I have other higher priority work recently and I fot this plan, so I'm very sorry. I will study it as soon as possible according to your answer. – poison Commented Mar 12 at 6:20
Add a comment  | 

1 Answer 1

Reset to default 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:

  • a parent QMenu having sub menus;
  • a QMenuBar with multiple menus, each one shown as the title of those menu;
  • a QToolButton using 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 an [the] action is activated by the user";

Considering all the above, the result is that:

  • when triggering an action in a menu (by clicking it, by pressing Enter when selected, or by explicitly calling trigger()), only that action will emit the triggered signal;
  • whenever an action in the current menu or menu bar (including actions in a sub menu) is triggered, the QMenu or QMenuBar will emit its 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.

发布评论

评论列表(0)

  1. 暂无评论