如何反复浏览菜单';Qt中的动作是什么?

如何反复浏览菜单';Qt中的动作是什么?,qt,qmenu,qmenubar,Qt,Qmenu,Qmenubar,我在一个项目中工作,需要自动打开(显示或弹出)QMenuBar中的项 假设我有下一个菜单栏: File Edit Help -op1 -op1 -op1 -op2 -op2 -op2 要设置操作(显示与该操作关联的菜单),我使用: 据我所知,我可以使用以下方法之一获取指向QMenuBar元素的指针列表: QMenuBar::actions(); 或 在所有这些情况下,a不为空,但当我尝试获取操作名QActio

我在一个项目中工作,需要自动打开(显示或弹出)QMenuBar中的项

假设我有下一个菜单栏:

 File     Edit      Help
   -op1     -op1      -op1
   -op2     -op2      -op2
       
要设置操作(显示与该操作关联的菜单),我使用:

据我所知,我可以使用以下方法之一获取指向QMenuBar元素的指针列表:

QMenuBar::actions();

在所有这些情况下,
a
不为空,但当我尝试获取操作名
QAction::title()
时,它总是导致我出现分段错误

我一直在搜索,发现在获取菜单栏操作列表后,可以请求
QAction::menu()
(如果项目是菜单,则返回有效的QMenu指针)以了解该项目是否是QMenu,如果是,可以重复获取该菜单的操作列表,并继续迭代。但这对我来说不起作用,我希望是这样

QList<Object*> lst2 = QMenuBar::findChildren<QAction*>();
QList lst2=QMenuBar::findChildren();

每个元素“File,Edit Help”
QAction::menu()
都会返回一个有效的菜单指针,因此我可以获取每个菜单的操作列表,但这对我来说根本不起作用。

qobject_cast失败的原因是,只有三个QAction将QMenuBar作为父项。其他三个是不同的QoObject(我猜是三个QMenus),因此强制转换失败。然后,与这些菜单相关联的qaction位于这些菜单下,而不是根QMenuBar下。我不明白为什么不能通过递归迭代QMenus来构建qaction的主列表


如果您在一个已知的菜单之后,可能无法触发父菜单,那么您可以使用UI定义中的QAction指针。如果您正在尝试自动化测试,那么所需QAction上的trigger()可能会根据您的需要进行详细说明。如果您试图对用户操作做出响应,修改工具栏可能是一种更好的上下文反馈方式,因为它不会破坏焦点。更多关于您实际尝试完成的内容的详细信息将有所帮助。

下面是如何迭代菜单栏中的每个菜单项,它还将查找下面的任何菜单,因此不需要在此处进行递归调用

// assuming you have a private QActionGroup* actions; defined in the header..
// ...and a slot named 'onAction(QAction*)' as well... this should work:
QList<QMenu*> lst;
lst = ui->menuBar->findChildren<QMenu*>();
actions = new QActionGroup(this);
foreach (QMenu* m, lst)
{
    foreach (QAction* a, m->actions())
    {
        actions->addAction(a);
    }
}
connect(actions,SIGNAL(triggered(QAction*)),this,SLOT(onAction(QAction*)));
//假设您有一个私有QActionGroup*操作;在标题中定义。。
//…还有一个名为“onAction(QAction*)”的插槽。。。这应该起作用:
QList-lst;
lst=ui->menuBar->findChildren();
动作=新QActionGroup(本);
foreach(qmen*m,lst)
{
foreach(QAction*a,m->actions())
{
行动->添加行动(a);
}
}
连接(动作、信号(触发的(QAction*)、此、插槽(onAction(QAction*));
正如您所看到的,您可以连接一个主插槽来处理一个操作可能引发的各种事件(我刚才在这里显示了触发器,但您明白了)。希望这有帮助。。某人

注释
例如,我使用QActionGroup来使用您可能会反复访问的列表,但是您确实不应该使用它,除非您处理的是广播组,因为这就是它的用途。其次,如果您想要这些操作,因为您计划将它们链接到一个方法来处理所有项目,我建议您使用QMenu的触发/悬停信号,或者如果您需要知道菜单何时将弹出,则需要QMenuBar的aboutToShow()信号。我想不出一个理由(无论如何对我来说)你不能在那些信号中做你需要做的事情,因为你在插槽中通过了QAction*。但是如果你必须用另一种方法,你可以用我上面展示的方法,你可能不想使用QActionGroup,因为它是为无线电分组而设计的。(您可以通过不向组中添加“可检查”的项来解决此问题。

枚举
QMenu
的正确方法是使用
操作()
函数,但有一个陷阱-一些操作是子菜单,需要递归迭代。事实上,每个
QMenu
都与
QAction
关联,它们都持有指向彼此的指针-请参阅和

理解每个QMenu也与一个QAction相关联是至关重要的。因此,正确的实现如下所示:

void enumerateMenu(QMenu *menu)
{
    foreach (QAction *action, menu->actions()) {
        if (action->isSeparator()) {
            qDebug("this action is a separator");
        } else if (action->menu()) {
            qDebug("action: %s", qUtf8Printable(action->text()));
            qDebug(">>> this action is associated with a submenu, iterating it recursively...");
            enumerateMenu(action->menu());
            qDebug("<<< finished iterating the submenu");
        } else {
            qDebug("action: %s", qUtf8Printable(action->text()));
        }
    }
}
void枚举菜单(QMenu*菜单)
{
foreach(QAction*操作,菜单->操作(){
如果(操作->isSeparator()){
qDebug(“此操作是分隔符”);
}else if(操作->菜单()){
qDebug(“操作:%s”,QUTF8可打印(操作->文本());
qDebug(“>>>此操作与子菜单关联,递归地对其进行迭代…”);
枚举菜单(操作->菜单());

qDebug(“这把它放在一起:

template <class Function>
class QMenuBarIterator {
    QMenuBar    *i_barP;

    void    iterate_sub(Function f, size_t tabsL, QMenu* m) {
        foreach (QAction *action, m->actions()) {
            f(tabsL, action);

            if (action->menu()) {
                iterate_sub(f, tabsL + 1, action->menu());
            }
        }
    }

    public:
    QMenuBarIterator(QMenuBar *barP) : i_barP(barP) {}

    virtual void operator()(size_t levelL, QAction *actionP) {
    }

    void    iterate(Function f) {
        QList<QMenu *>  menuBar = i_barP->findChildren<QMenu *>();

        foreach (QMenu* m, menuBar) {
            f(0, m->menuAction());
            iterate_sub(f, 1, m);
        }
    }
};

/***************************************************************************/
class CMenuLogger {
    public:

    void operator()(size_t tabsL, QAction *action) {
        SuperString     tabStr(GetIndentString(tabsL)); //  returns a string with tabsL tab characters in it

        if (action->isSeparator()) {
            qDebug("%s-------------------", tabStr.utf8Z());

        } else {
            qDebug("%s%s (%s)",
                tabStr.utf8Z(),
                qUtf8Printable(action->text()),
                qUtf8Printable(action->objectName()));
        }
    }
};
模板
qmenubariator类{
QMenuBar*i_barP;
无效迭代子函数(函数f,大小选项卡,QMenu*m){
foreach(QAction*action,m->actions()){
f(tabsL,行动);
如果(操作->菜单()){
迭代(f,tabsL+1,动作->菜单());
}
}
}
公众:
qmenubariator(QMenuBar*barP):i_barP(barP){}
虚拟void运算符()(大小\u t级别,QAction*actionP){
}
无效迭代(函数f){
QList menuBar=i_barP->findChildren();
foreach(QMenu*m,菜单栏){
f(0,m->menuAction());
迭代(f,1,m);
}
}
};
/***************************************************************************/
CMenuLogger类{
公众:
void运算符()(大小选项卡,QAction*action){
超级字符串tabStr(GetIndentString(tabsL));//返回一个包含tabsL tab字符的字符串
如果(操作->isSeparator()){
qDebug(“%s-----------------”,tabStr.utf8Z());
}否则{
qDebug(“%s%s(%s)”,
tabStr.utf8Z(),
QUTF8可打印(操作->文本()),
QUTF8可打印(操作->对象名());
}
}
};
那么在你的主要发言中:

{
    QMenuBarIterator<CMenuLogger>           bar(ui->menuBar);

    bar.iterate(CMenuLogger());
}
{
qmenubariator栏(用户界面->菜单栏);
迭代
void enumerateMenu(QMenu *menu)
{
    foreach (QAction *action, menu->actions()) {
        if (action->isSeparator()) {
            qDebug("this action is a separator");
        } else if (action->menu()) {
            qDebug("action: %s", qUtf8Printable(action->text()));
            qDebug(">>> this action is associated with a submenu, iterating it recursively...");
            enumerateMenu(action->menu());
            qDebug("<<< finished iterating the submenu");
        } else {
            qDebug("action: %s", qUtf8Printable(action->text()));
        }
    }
}
template <class Function>
class QMenuBarIterator {
    QMenuBar    *i_barP;

    void    iterate_sub(Function f, size_t tabsL, QMenu* m) {
        foreach (QAction *action, m->actions()) {
            f(tabsL, action);

            if (action->menu()) {
                iterate_sub(f, tabsL + 1, action->menu());
            }
        }
    }

    public:
    QMenuBarIterator(QMenuBar *barP) : i_barP(barP) {}

    virtual void operator()(size_t levelL, QAction *actionP) {
    }

    void    iterate(Function f) {
        QList<QMenu *>  menuBar = i_barP->findChildren<QMenu *>();

        foreach (QMenu* m, menuBar) {
            f(0, m->menuAction());
            iterate_sub(f, 1, m);
        }
    }
};

/***************************************************************************/
class CMenuLogger {
    public:

    void operator()(size_t tabsL, QAction *action) {
        SuperString     tabStr(GetIndentString(tabsL)); //  returns a string with tabsL tab characters in it

        if (action->isSeparator()) {
            qDebug("%s-------------------", tabStr.utf8Z());

        } else {
            qDebug("%s%s (%s)",
                tabStr.utf8Z(),
                qUtf8Printable(action->text()),
                qUtf8Printable(action->objectName()));
        }
    }
};
{
    QMenuBarIterator<CMenuLogger>           bar(ui->menuBar);

    bar.iterate(CMenuLogger());
}