Qt: Change application QMenuBar contents on Mac OS X

Deadly 提交于 2019-12-04 16:53:45

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

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

m_menuBar->addMenu("One");

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());

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());
}

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

  • It's possible to disable QMenuBar native behavior by using QMenuBar::setNativeMenuBar
  • Because of turned on by default QMenuBar native behavior, QActions with standard OS X titles("About","Quit") will be placed automatically by Qt in the predefined way on the screen; Empty QMenu instances will be not showed at all.

I think your problem is this line:

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

To add menus to a menubar you'd want code as follows:

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

To create menus, and then add actions, and then add the menu to the menu bar:

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

QMenuBar *t = new QMenuBar;
t->addMenu( item );
t->show();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!