如何在Qt中动态添加菜单

4

我想动态地给菜单项添加子菜单。我该如何实现?

我尝试了这样做,首先我创建了一个操作和子菜单,然后将子菜单添加到操作中。但是,当我连接操作的“触发”信号时,如果我点击该操作,程序会崩溃。

我还处理了菜单的“aboutToShow”信号,但同样在我点击操作时也会崩溃。

以下是示例代码:

Submenu = new QMenu(this);      
connect(Submenu, SIGNAL( aboutToShow()), this, SLOT(move ()));

                  QAction *test = new QAction(tr("Selection"), this);
                  test ->setMenu(Submenu);

                 menubar()->addAction(test);

在显示子菜单之前,我希望能收到通知。

附加信息:

请在您的主窗口构造函数中尝试此代码。

QAction *action = new QAction("Test",this);
QAction *dummyaction = new QAction("Testing",this);
QMenu *menu = new QMenu();
menu->addAction(dummyaction);

bool val= connect(menu, SIGNAL( aboutToShow()), this, SLOT( Move()));
val= connect(menu, SIGNAL( aboutToHide()), this, SLOT(Move()));

action->setMenu(menu);
this->menuBar()->addAction(action);

如果我这样做,我就能看到一个子菜单项。但在此之前,Move slot 应该被调用,但它没有被调用...即使在隐藏之前也应该调用相同的 slot,但它没有出现...

我尝试了 connect 的返回值... 它是 true 的... 那么我的代码有什么问题... 请告诉我...

2个回答

3
这样的代码应该可以工作:
QMainWindow wnd;
QAction *act = wnd.menuBar()->addMenu("SomeMenu")->addMenu("someSubmenu")->addAction("someAction");
QObject::connect(act,SIGNAL(triggered()),
                 someObj,SLOT(actionReaction()));

我认为addMenu() addAction()应该以更可靠的方式工作。这种方法对我有效。

1
所以你想每次打开菜单时都重新填充它,我理解的对吗?你是否在move()函数中删除了菜单的先前操作? - VestniK
我不想填充任何菜单...只需在“附加信息”下添加以下代码并尝试在mainwindow构造函数中查看行为...我不明白为什么会发出“abouttoshow”信号。你能否请检查一下..这是一个错误吗?还是我漏掉了什么东西。 - Naruto
我刚刚尝试创建了一个新项目。我创建了一个从QMainWindow派生的类,完全没有更改你的代码,并创建了一个Move槽,其中包含以下代码:qDebug("Moved"); 应用程序按预期工作。没有出现任何崩溃,并且每次菜单显示或隐藏时在控制台上都可以看到“Moved”文本。你的问题不会在你发布的代码中。 - VestniK
你正在使用Symbian吗?你能否移动到“Move”插槽吗? 我的意思是,你要去“Move”插槽吗?尝试在调试模式下,在“Move”插槽中放置一个消息框。 - Naruto
我已经在我的Linux桌面上(Kubuntu 10.04 Qt 4.6.2)尝试运行了这段代码。正如我所说,我已经在我的QMainWindow子类中创建了Move()槽,它只是将"Movess"行打印到终端上。代码的运行结果完全符合预期。 - VestniK
显示剩余2条评论

2

我不确定您想在Move()槽中做什么。

但这是您自己的代码(我删除了对我来说似乎无用的部分),经过修改后在我的计算机上不会崩溃:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QAction>
#include <QMenu>

class MainWindow : public QMainWindow
{
   Q_OBJECT

public:
   explicit MainWindow(QWidget *parent = 0);

private:
   QMenu* menu;
   QAction *dummyaction;
   QMenu* m_pSubMenu;
 private slots:
    void Move();
};

#endif // MAINWINDOW_H

mainwindow.cpp :

#include "mainwindow.h"

#include <QMenuBar>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
   m_pSubMenu = NULL;
   QMenuBar* pMenuBar = new QMenuBar(this);

   setMenuBar(pMenuBar);

   dummyaction = new QAction("Testing",this);
   menu = new QMenu("Test", this);
   menu->addAction(dummyaction);
   this->menuBar()->addMenu(menu);

   connect(menu, SIGNAL(aboutToShow()), this, SLOT(Move()));
}

void MainWindow::Move() {
   if (!m_pSubMenu) {
      m_pSubMenu = new QMenu(menu);
      dummyaction->setMenu(m_pSubMenu);
   }
   QAction* pAction = new QAction("Test", this);
   m_pSubMenu->addAction(pAction);
}

我不确定您想在 Move() 槽函数中实现什么功能,但以下是一个示例:每次调用 Move() 槽函数时都会添加一个新的子菜单项。
希望这能帮到您。

是的,我已经在我的诺基亚模拟器中尝试过了。它可以正常工作而不会崩溃,但是当我单击“测试”主菜单时,子菜单“测试”没有被添加。 我的意思是,aboutToShow() 信号本身没有发出... 我认为这是 Qt Symbian 中的一个错误。您使用的是哪个版本的 Qt?以及您使用的是桌面环境还是移动环境? - Naruto
如果你认为这是Qt在Symbian实现中的一个bug,我认为你应该在Qt问题跟踪器http://bugreports.qt.nokia.com上发布一个bug。我已经有过这样的经历,可以说诺基亚的支持工程师非常友好。 - VestniK
谢谢, 是的,你说得对,它们就是这样。 我也已经发布了一个错误报告,一旦我从他们那里得到任何更新,我会通知你。 - Naruto
我正在使用基于Qt 4.6.1的Qt Creator 1.3.1,在Windows XP上。 - Jérôme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接