Qt:在Mac OS X上更改应用程序QMenuBar内容

时间:2014-09-23 21:13:54

标签: c++ macos qt qmenu qmenubar

我的应用程序将QTabWidget用于多个“页面”,其中顶级菜单会根据用户所在的页面而改变。

我的问题是尝试重新创建菜单栏的内容会导致重大显示问题。除了Mac OS X之外,它在第一和第三种风格(没有测试第二种,但我宁愿不使用那种风格)上的工作正常。

第一个菜单是按照我在应用程序中创建最多的方式创建的,它们会收到正确的标题,但只要重新创建菜单就会消失。

第二个菜单同时出现在初始填充和菜单栏的重新填充上,但在两种情况下都有标签“无标题”。第二个菜单的样式仅在尝试解决此问题时创建,因此这是我能够有一个菜单的唯一方法。

第三个动态菜单永远不会出现,期间。我使用此样式动态填充即将显示的菜单。

我尝试删除QMenuBar并使用

重新创建一个
m_menuBar = new QMenuBar(0);

并使用它而不是m_menuBar->clear(),但它具有相同的行为。

我没有足够的声誉来内联发布图片,因此我将包含imgur链接:

启动行为http://i.imgur.com/ZEvvGKl.png

发布按钮点击行为http://i.imgur.com/NzRmcYg.png

我创建了一个最小的示例,可以在Mac OS X 10.9.4上使用Qt 5.3重现此行为。

mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    m_menuBar = new QMenuBar(0);
    m_dynamicMenu = new QMenu("Dynamic");
    connect(m_dynamicMenu, SIGNAL(aboutToShow()), this, SLOT(updateDynamicMenu()));

    changeMenuBar();

    QPushButton *menuBtn = new QPushButton("Test");
    connect(menuBtn, SIGNAL(clicked()), this, SLOT(changeMenuBar()));

    setCentralWidget(menuBtn);
}

void MainWindow::changeMenuBar() {
    m_menuBar->clear();

    // Disappears as soon as this is called a second time
    QMenu *oneMenu = m_menuBar->addMenu("One");
    oneMenu->addAction("foo1");
    oneMenu->addAction("bar1");
    oneMenu->addAction("baz1");

    // Stays around but has 'Untitled' for title in menu bar
    QMenu *twoMenu = new QMenu("Two");
    twoMenu->addAction("foo2");
    twoMenu->addAction("bar2");
    twoMenu->addAction("baz2");
    QAction *twoMenuAction = m_menuBar->addAction("Two");
    twoMenuAction->setMenu(twoMenu);

    // Never shows up
    m_menuBar->addMenu(m_dynamicMenu);
}

void MainWindow::updateDynamicMenu() {
    m_dynamicMenu->clear();
    m_dynamicMenu->addAction("foo3");
    m_dynamicMenu->addAction("bar3");
    m_dynamicMenu->addAction("baz3");
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtWidgets>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);

private slots:
    void changeMenuBar();
    void updateDynamicMenu();

private:
    QMenuBar *m_menuBar;
    QMenu *m_dynamicMenu;
};

#endif // MAINWINDOW_H

2 个答案:

答案 0 :(得分:2)

所有这些看起来都像OS X上的Qt bug。实际上它是一个很老的bug。

您可以通过QMenuBar :: addMenu函数调用来解决方法并且无法使用QMenu,就像您在此处一样:

m_menuBar->addMenu("One");

通过动态创建QMenu实例从QMenu检索QAction,然后为QMenu :: menuAction检索的QAction实例调用QMenuBar :: addAction,而不是此工作,如下所示:

m_menuBar->addAction(oneMenu->menuAction());

如果你想动态创建一些特定的菜单项,你可以使用QMenuBar :: removeAction和QMenuBar :: insertAction。

根据您的源代码,它的修改版本处理所有菜单动态创建每次点击按钮(您在源代码中执行此操作)和菜单&#39;动态&#39;每次单击按钮时,都会填充不同的项目数。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtWidgets>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);

private slots:
    void changeMenuBar();

private:
    QMenuBar *m_menuBar;
    QMenu *m_dynamicMenu;
    int m_clickCounter;

};

#endif // MAINWINDOW_H
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      m_clickCounter(1)
{
    m_menuBar = new QMenuBar(this);

    connect(m_dynamicMenu, SIGNAL(aboutToShow()), this, SLOT(updateDynamicMenu()));

    changeMenuBar();

    QPushButton *menuBtn = new QPushButton("Test");
    connect(menuBtn, SIGNAL(clicked()), this, SLOT(changeMenuBar()));

    setCentralWidget(menuBtn);
}

void MainWindow::changeMenuBar() {
    ++m_clickCounter;

    m_menuBar->clear();

    QMenu *oneMenu = new QMenu("One");

    oneMenu->addAction("bar1");
    oneMenu->addAction("baz1");
    m_menuBar->addAction(oneMenu->menuAction());

    QMenu *twoMenu = new QMenu("Two");
    twoMenu->addAction("foo2");
    twoMenu->addAction("bar2");
    twoMenu->addAction("baz2");

    m_menuBar->addAction(twoMenu->menuAction());

    m_dynamicMenu = new QMenu("Dynamic");
    for (int i = 0; i < m_clickCounter; ++i) {
        m_dynamicMenu->addAction(QString("foo%1").arg(i));
    }

    m_menuBar->addAction(m_dynamicMenu->menuAction());
}

此外,在为OS X开发菜单逻辑时,请记住:

  • 可以使用QMenuBar :: setNativeMenuBar
  • 禁用QMenuBar本机行为
  • 由于默认启用了QMenuBar原生行为,Qt将以预定义的方式自动放置标准OS X标题(&#34;关于&#34;,&#34;退出&#34;)的QActions屏幕;空QMenu实例根本不会显示。

答案 1 :(得分:1)

我认为你的问题就在这一行:

QMenu *oneMenu = m_menuBar->addMenu("One");

要向菜单栏添加菜单,您需要以下代码:

QMenuBar *m = new QMenuBar;
m->addMenu( new QMenu("Hmmm") );
m->show();

创建菜单,然后添加操作,然后将菜单添加到菜单栏:

QMenu *item = new QMenu( "Test1" );
item->addAction( "action1" );

QMenuBar *t = new QMenuBar;
t->addMenu( item );
t->show();