的Qt:在Mac OS X
我的应用程序,来改变应用QMenuBar内容使用QTabWidget多个“页”,其中取决于顶层菜单更改的用户是在什么页面。的Qt:在Mac OS X
我的问题是,试图重新创建在各大显示器问题菜单栏的结果内容。它的工作原理与第一和第三样式预期(没有第二次测试,但我宁愿不使用该样式)在所有平台上,除了针对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
我创建了一个用Qt 5.3在Mac OS X 10.9.4上重现此行为的最小示例。
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
这一切看起来Qt的错误在OS X上,这是非常老的bug,其实。
你可以做的解决办法,不通过QMenuBar :: addMenu函数调用与QMenu工作,因为你在这里做的:
m_menuBar->addMenu("One");
而是用的QAction这项工作由创作从QMenu检索到的QMenu例如动态,然后调用QMenuBar ::的addAction由QMenu :: menuAction检索的QAction实例,如下:
m_menuBar->addAction(oneMenu->menuAction());
除了QMenuBar ::的addAction可以使用QMenuBar :: removeAction和QMenuBar ::在sertAction,如果你只想创建一些特定的菜单项动态。
根据你的源代码,它是它的修改版本,它处理所有菜单动态创建每个按钮单击(你在源代码中这样做),菜单'动态'填充每次不同数量的项目你点击按钮。
#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原生行为,具有标准OS X标题的QActions(“关于”,“退出”)将由Qt以预定义的方式自动放置在屏幕上;空的QMenu实例将不会显示。
我觉得你的问题是这一行:
QMenu *oneMenu = m_menuBar->addMenu("One");
要菜单添加到菜单栏你'd想要代码如下:
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();
我想指出,虽然增加'oneMenu-> menuAction()'是正确的,并且适用于前2个,它显然是**强制**(在Mac OS X上)菜单添加到“QMenuBar”时有现有的操作。由于我的动态菜单示例在发出'aboutToShow()'信号之前不会添加动作,因此我的解决方法是使用1'QAction'来填充动态菜单,除了使其初始显示外,其他任何功能都无用。在我的'updateDynamicMenu()'插槽中,我清除并重新填充动态菜单。 – syrius 2014-09-24 18:19:06
@syrius,只是为了说明,通过使用QMenuBar :: setNativeMenuBar可以禁用菜单栏平台原生行为。但是这会带来更多令人头痛的问题。 同样在实际应用中,我们使用QActions来监听它们的信号。为避免开销,最佳解决方案转变为将所有QAction保留为私有成员,并在每次需要更改QMenu时为其填充动态菜单。 – 2014-09-24 19:00:35
,但是在实际的应用程序中,例如编辑器的“窗口”菜单,对于当前打开的每个文件都不会有私有成员操作。这就是为什么我在连接到'aboutToShow()'信号的插槽中填充菜单的原因。我只是提到,在你的动态菜单的例子中,如果你没有填充它,直到'aboutToShow()'信号发出,它将永远不会出现在菜单栏中,这是我发布我的初始评论的原因需要一个空的QAction(因为你还不知道内容)。我认为将其纳入答案对其他人有所帮助。 – syrius 2014-09-24 19:02:15