2014-09-23 170 views
1

我的應用程序,來改變應用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 

回答

1

這一切看起來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實例將不會顯示。
+2

我想指出,雖然增加'oneMenu-> menuAction()'是正確的,並且適用於前2個,它顯然是**強制**(在Mac OS X上)菜單添加到「QMenuBar」時有現有的操作。由於我的動態菜單示例在發出'aboutToShow()'信號之前不會添加動作,因此我的解決方法是使用1'QAction'來填充動態菜單,除了使其初始顯示外,其他任何功能都無用。在我的'updateDynamicMenu()'插槽中,我清除並重新填充動態菜單。 – syrius 2014-09-24 18:19:06

+0

@syrius,只是爲了說明,通過使用QMenuBar :: setNativeMenuBar可以禁用菜單欄平臺原生行爲。但是這會帶來更多令人頭痛的問題。 同樣在實際應用中,我們使用QActions來監聽它們的信號。爲避免開銷,最佳解決方案轉變爲將所有QAction保留爲私有成員,並在每次需要更改QMenu時爲其填充動態菜單。 – 2014-09-24 19:00:35

+0

,但是在實際的應用程序中,例如編輯器的「窗口」菜單,對於當前打開的每個文件都不會有私有成員操作。這就是爲什麼我在連接到'aboutToShow()'信號的插槽中填充菜單的原因。我只是提到,在你的動態菜單的例子中,如果你沒有填充它,直到'aboutToShow()'信號發出,它將永遠不會出現在菜單欄中,這是我發佈我的初始評論的原因需要一個空的QAction(因爲你還不知道內容)。我認爲將其納入答案對其他人有所幫助。 – syrius 2014-09-24 19:02:15

1

我覺得你的問題是這一行:

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