Qt:在Mac OS X上更改应用程序QMenuBar的内容 [英] Qt: Change application QMenuBar contents on Mac OS X

查看:413
本文介绍了Qt:在Mac OS X上更改应用程序QMenuBar的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序将QTabWidget用于多个页面",其中顶层菜单根据用户所在的页面而变化.

My application uses a QTabWidget for multiple 'pages', where the top-level menu changes depending on what page the user is on.

我的问题是,尝试重新创建菜单栏的内容会导致严重的显示问题.在Mac OS X以外的所有平台上,它都可以在第一种和第三种样式(没有经过第二次测试,但我不想使用该样式)下按预期工作.

My issue is that attempting to re-create the contents of the menu bar results in major display issues. It works as expected with the first and third style (haven't tested second, but I'd rather not use that style) on all platforms except for Mac OS X.

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

The first menu is created in the way I create most in the application, and they receive the correct title, but disappear as soon as the menu is re-created.

第二个菜单同时出现在初始菜单栏和重新填充的菜单栏中,但在两种情况下均带有标签"Untitled".仅在尝试解决此问题时才创建第二个菜单的样式,因此这是我能够保留菜单的唯一方法.

The second menu appears both on the initial population and the re-population of the menu bar, but in both cases has the label "Untitled". The style for the second menu was only created when trying to solve this, so it's the only way I've been able to have a menu stick around.

第三个动态菜单永远不会出现.我使用这种样式来动态填充将要显示的菜单.

The third dynamic menu never appears, period. I use this style for dynamically populating menus that are about to show.

我尝试删除QMenuBar并使用创建一个

I have tried deleting the QMenuBar and re-creating one with

m_menuBar = new QMenuBar(0);

并使用它与m_menuBar->clear()相对,但它具有相同的行为.

and using that as opposed to m_menuBar->clear() but it has the same behavior.

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

I don't have enough reputation to post images inline, so I'll include the imgur links:

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

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

我创建了一个最小示例,以在带有Qt 5.3的Mac OS X 10.9.4上重现此行为.

I have created a minimal example to reproduce this behavior on Mac OS X 10.9.4 with 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

推荐答案

所有这些看起来都像OS X上的Qt错误.实际上,这是一个非常古老的错误.

All this looks like Qt bug on OS X. And it's very old bug, actually.

您可以执行解决方法,并且不能通过QMenuBar :: addMenu函数调用来使用QMenu,就像您在此处所做的那样:

You can do workaround and don't work with QMenu via QMenuBar::addMenu function calls, as you do here:

m_menuBar->addMenu("One");

通过动态创建QMenu实例,然后为QMenu :: menuAction检索到的QAction实例调用QMenuBar :: addAction来代替从QMenu检索QAction的工作,如下所示:

Instead of this work with QAction retrieved from QMenu by creation of the QMenu instance dynamically and then calling of QMenuBar::addAction for the QAction instance retrieved by QMenu::menuAction, as following:

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

如果要仅动态创建某些特定菜单项,则除了QMenuBar :: addAction外,还可以使用QMenuBar :: removeAction和QMenuBar :: insertAction.

Beside QMenuBar::addAction you can use QMenuBar::removeAction and QMenuBar::insertAction if you want to make creation only of some specific menu items dynamically.

基于此处的源代码,它是其修改后的版本,可处理每次单击按钮时动态创建的所有菜单(您在源代码中执行此操作),并且每次您在菜单动态"中填充的项目数都不相同点击按钮.

Based on your source code here it's modified version of it which deals with all menus dynamic creation on every button click (you do this in your source code) and the menu 'Dynamic' is populated with different count of items every time you click the button.

#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开发菜单逻辑时,请记住:

Additionally while developing menus logic for OS X it's good to remember:

  • 可以使用QMenuBar :: setNativeMenuBar禁用QMenuBar的本机行为
  • 由于默认情况下QMenuBar的本机行为处于打开状态,因此带有标准OS X标题(关于",退出")的QAction将由Qt以预定义的方式自动放置在屏幕上;空的QMenu实例将完全不显示.

这篇关于Qt:在Mac OS X上更改应用程序QMenuBar的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆