Qt: changing the contents of a QMenuBar application on Mac OS X

My application uses QTabWidget for several "pages", where the top-level menu changes depending on which page the user is on.

My problem is that trying to recreate the contents of the menu bar leads to serious display issues. It works as expected with the first and third style (the second was not tested, but I would not use this style) on all platforms except Mac OS X.

The first menu is created the way I create the majority in the application, and they get the correct title, but disappear as soon as the menu is created.

The second menu appears both on the initial population and on the re-populated menu bar, but in both cases there is a label β€œUntitled”. The style for the second menu was only created when trying to solve this problem, so this is the only way I could stick to the menu.

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

I tried uninstalling QMenuBar and re-creating it with

m_menuBar = new QMenuBar(0);

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

I don't have enough reputation to post images in a string, so I will include imgur links:

Launch Actions : 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
+1
2

Qt OS X. , .

QMenu QMenuBar:: addMenu, :

m_menuBar->addMenu("One");

QAction, QMenu, QMenu , QMenuBar:: addAction QAction, QMenu:: menuAction, :

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

QMenuBar:: addAction QMenuBar:: removeAction QMenuBar:: insertAction, .

, ( ), "" , .

#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 QMenuBar:: setNativeMenuBar
  • - QMenuBar, QActions OS X ( "", "" ) Qt ; QMenu .
+2

, :

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

All Articles