如何在 Qt 中迭代菜单的操作?
我正在一个项目中工作,我需要自动打开(显示或弹出)QMenuBar 中的项目。
假设我有下一个菜单栏:
File Edit Help
-op1 -op1 -op1
-op2 -op2 -op2
要设置一个操作(显示与该操作关联的菜单),我使用:
menuBar->setActiveAction(mymenuactionpointer);
据我所知,我可以使用以下方法之一来获取指向 QMenuBar 元素的指针列表:
QMenuBar::actions();
或
QList<Object*> lst1 = QMenuBar::findChildren<QObject*>();
QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();
When我使用 QMenuBar::findChildren
或 MenuBar::actions()
我得到了菜单栏中的菜单列表,我的意思是,我从 QMenuBar 中获取了 "File, Edit, Help"
,本例中 QList 的大小为 3。
当我使用 QMenuBar::findChildren
QAction *a = (QAction *)lst1.at(0);
QAction *a = qobject_cast<QAction*>(lst1.at(0));
QAction *a = dynamic_cast<QAction*>(lst1.at(0));
在所有这些情况下 a
不为 NULL,但是当我尝试获取操作名称 QAction::title()
时,它总是会导致我的分段错误。
我一直在搜索,在这里找到了菜单栏操作列表,可以询问 QAction::menu()
(如果该项目是菜单,则返回一个有效的 QMenu 指针)来了解该项目是否是 QMenu,如果是的,可以重复获取该菜单的操作列表,并继续迭代。但这对我不起作用,我希望对于
QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();
每个元素“文件,编辑帮助”QAction::menu()
返回一个有效的菜单指针,这样我就可以获得每个元素的操作列表菜单,但这对我来说根本不起作用。
I'm working in a project where I need to open (show or popup) automatically the items in the QMenuBar.
Let's say I have the next menu bar:
File Edit Help
-op1 -op1 -op1
-op2 -op2 -op2
To set an action (show the menu associated with that action) I use:
menuBar->setActiveAction(mymenuactionpointer);
As I know, I can use one of the following to get a list of pointers to the elements of QMenuBar:
QMenuBar::actions();
or
QList<Object*> lst1 = QMenuBar::findChildren<QObject*>();
QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();
When I use QMenuBar::findChildren<QAction*>()
or MenuBar::actions()
I got a list of the menus in menubar, I mean, I got "File, Edit, Help"
from my QMenuBar, the size of the QList in this case is 3.
When I use QMenuBar::findChildren<QObject*>()
I got a list of QObject of size 6, which is the correct number of items in the menu bar. However, I have tried cast to QAction*
QAction *a = (QAction *)lst1.at(0);
QAction *a = qobject_cast<QAction*>(lst1.at(0));
QAction *a = dynamic_cast<QAction*>(lst1.at(0));
In all this cases a
is not NULL, but when I try to get the action name QAction::title()
it always causes me segmentation fault.
I have been searching and I found here that after getting the menubar actions list, one can ask to QAction::menu()
(which returns a valid QMenu pointer if the item is a menu) to know if the item is a QMenu, if yes, one can repeat getting the actions list of that menu, and continue iterating. But this does not work for me, I expected that for
QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();
each element "File, Edit Help" QAction::menu()
returns a valid menu pointer, so I could get the list of the actions of each menu, but this does not work at all for me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
枚举
QMenu
的正确方法是使用actions()
函数,但有一个问题 - 某些操作是子菜单,需要递归迭代。事实上,每个QMenu
都与一个QAction
关联,并且它们都持有彼此的指针 - 请参阅 QMenu::menuAction() 和 QAction::menu()。理解每个 QMenu 还与一个 QAction 相关联是至关重要的。因此,知道了这一点,正确的实现如下:
The correct way to enumerate a
QMenu
is to use theactions()
functions, but there is a catch - some of the actions are submenus, and they need to be iterated recursively. In fact, eachQMenu
is associated with aQAction
, and they both hold pointers to each other - see QMenu::menuAction() and QAction::menu().It is crucial to understand that each QMenu is also associated with a QAction. So knowing that, the proper implementation is the following:
下面是如何迭代菜单栏中的每个菜单项,它还会查找下面的任何菜单,因此这里不需要递归调用。
正如您所看到的,您可以连接一个主插槽来处理操作可能引发的各种事件(我刚刚在此处显示了触发,但您明白了)。希望这可以帮助..某人..
笔记
我使用 QActionGroup 作为示例,用于使用您可能会迭代的列表,但您确实不应该使用它,除非您正在处理无线电组,因为这就是它的用途。其次,如果您想要这些操作,因为您计划将它们链接到一个方法来处理所有项目,我建议您使用 QMenu 的触发/悬停信号,或者如果您需要知道何时将弹出菜单,您将需要QMenuBar 的 aboutToShow() 信号。我想不出一个原因(无论如何对我来说),因为你在插槽中传递了 QAction* ,所以你无法在这些信号中执行你需要的操作。但是,如果您必须以其他方式执行此操作,则可以按照我上面所示的方式执行此操作,您可能只是不想使用 QActionGroup,因为单选分组是它的设计目的。 (您可以通过不将“可检查”的项目添加到组中来解决此问题。
Below is how to iterate through every menu item in the menu bar, it will also seek out any menus underneath so there is not need for recursive calling here.
As you can see, you can then connect a master slot to handle the various events an action might bring up (i just showed triggered here but you get the idea). Hope this helps.. someone..
Notes
I used the QActionGroup for example purposes on using the list you might iterate through, but you really shouldnt use that unless you are dealing with radio groups since thats what its for. Secondly, if you want the actions because you plan to link them into a single method to handle all items, i suggest you use QMenu's triggered/hovering signals or if you need to know when a menu is about to pop up, you'll need QMenuBar's aboutToShow() signal. I cant think of a reason (for me anyway) that you cant do what you need in those signals since you are passed the QAction* in the slot. But if you MUST do it the otherway, you can do it the way I showed above, you just might not want to use the QActionGroup because of radio grouping is what it is designed for. (you can work around that by not adding items that are 'checkable' into the group.
qobject_cast 失败的原因是只有三个以 QMenuBar 作为父级的 QAction。其他三个是不同的 QObject(我猜是三个 QMenus),因此转换失败。与这些菜单关联的 QAction 位于这些菜单之下,而不是根 QMenuBar。我不明白为什么你不能通过递归迭代 QMenus 来构建 QActions 主列表。
如果您在使用已知菜单,则可能无法触发父菜单,您可能可以仅使用 UI 定义中的 QAction 指针。如果您正在尝试自动化测试,那么您所需的 QAction 上的 trigger() 可能会如您所需要的那样详细。如果您试图响应用户操作,修改工具栏可能是上下文反馈的更好方法,因为它不会破坏焦点。有关您实际想要完成的任务的更多详细信息将会有所帮助。
The reason the qobject_cast is failing is that there are only three QActions with the QMenuBar as the parent. The other three are different QObjects (my guess is the three QMenus), so the cast fails. The QActions associated with those menus are then under those, not the root QMenuBar. I fail to see why you can't build a master list of QActions by recursively iterating through the QMenus.
You may be able to just use the QAction pointer from your UI definition if you are after a known menu, that might not trigger the parent menus. If you are trying to automate testing, trigger() on your desired QAction is probably as detailed as you need. If you are trying to do things in response to user actions, modifying toolbars is probably a better means of contextual feedback, as it doesn't break focus. Some more details on what you're actually trying to accomplish would help.
这将它们放在一起:
然后在你的 main 中:
this puts it all together:
then in your main: