3

私のアプリケーションは、複数の「ページ」に QTabWidget を使用します。トップレベルのメニューは、ユーザーがどのページにいるかに応じて変化します。

私の問題は、メニュー バーの内容を再作成しようとすると、表示に重大な問題が発生することです。Mac OS X を除くすべてのプラットフォームで、1 番目と 3 番目のスタイル (2 番目はテストしていませんが、そのスタイルは使用したくない) で期待どおりに動作します。

最初のメニューは、私がアプリケーションで作成するほとんどの方法で作成され、正しいタイトルを受け取りますが、メニューが再作成されるとすぐに消えます。

2 番目のメニューは、メニュー バーの最初の作成と再作成の両方に表示されますが、どちらの場合も「無題」というラベルが付いています。2 番目のメニューのスタイルは、これを解決しようとしたときにのみ作成されたため、メニューを固定できる唯一の方法です。

3 番目の動的メニューは表示されません。表示しようとしているメニューを動的に設定するために、このスタイルを使用します。

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 でこの動作を再現する最小限の例を作成しました。

メインウィンドウ.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");
}

メインウィンドウ.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
4

2 に答える 2

4

これはすべて、OS X の Qt のバグのように見えます。実際には、非常に古いバグです。

ここで行うように、回避策を実行し、QMenuBar::addMenu 関数呼び出しを介して QMenu を使用しないでください。

m_menuBar->addMenu("One");

この作業の代わりに、QMenu インスタンスを動的に作成し、QMenu::menuAction によって取得された QAction インスタンスに対して QMenuBar::addAction を呼び出すことによって、QMenu から取得した QAction を次のように使用します。

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::setNativeMenuBar を使用して、QMenuBar のネイティブ動作を無効にすることができます。
  • QMenuBar のネイティブ動作がデフォルトでオンになっているため、標準の OS X タイトル ("About","Quit") を持つ QActions は、事前に定義された方法で画面に Qt によって自動的に配置されます。空の QMenu インスタンスはまったく表示されません。
于 2014-09-24T04:32:12.340 に答える