Beispiel für Menüs

Das Beispiel Menüs demonstriert, wie Menüs in einer Hauptfensteranwendung verwendet werden können.

Ein Menü-Widget kann entweder ein Pull-Down-Menü in einer Menüleiste oder ein eigenständiges Kontextmenü sein. Pull-Down-Menüs werden in der Menüleiste angezeigt, wenn der Benutzer auf den entsprechenden Eintrag klickt oder die angegebene Tastenkombination drückt. Kontextmenüs werden in der Regel durch eine spezielle Tastaturtaste oder durch einen Rechtsklick aufgerufen.

Ein Menü besteht aus einer Liste von Aktionspunkten. In Anwendungen können viele gängige Befehle über Menüs, Symbolleistenschaltflächen und Tastenkombinationen aufgerufen werden. Da der Benutzer erwartet, dass die Befehle unabhängig von der verwendeten Benutzeroberfläche auf die gleiche Weise ausgeführt werden, ist es sinnvoll, jeden Befehl als eine Aktion darzustellen.

Das Beispiel Menüs besteht aus einer einzigen Klasse, MainWindow, die von der Klasse QMainWindow abgeleitet ist. Wenn Sie eine der Aktionen in unserer Anwendung auswählen, wird der Pfad der Aktion in ihrem zentralen Widget angezeigt.

MainWindow Klassendefinition

QMainWindow bietet ein Hauptanwendungsfenster mit einer Menüleiste, Symbolleisten, Docking-Widgets und einer Statusleiste um ein großes zentrales Widget.

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow();

protected:
#ifndef QT_NO_CONTEXTMENU
    void contextMenuEvent(QContextMenuEvent *event) override;
#endif // QT_NO_CONTEXTMENU

In diesem Beispiel wird gezeigt, wie man Pulldown-Menüs und ein Kontextmenü implementiert. Um ein benutzerdefiniertes Kontextmenü zu implementieren, müssen wir die Funktion contextMenuEvent() von QWidget neu implementieren, um die Kontextmenüereignisse für unser Hauptfenster zu empfangen.

private slots:
    void newFile();
    void open();
    void save();
    void print();
    void undo();
    void redo();
    void cut();
    void copy();
    void paste();
    void bold();
    void italic();
    void leftAlign();
    void rightAlign();
    void justify();
    void center();
    void setLineSpacing();
    void setParagraphSpacing();
    void about();
    void aboutQt();

Wir müssen auch eine Sammlung privater Slots implementieren, um auf die Aktivierung eines unserer Menüeinträge durch den Benutzer zu reagieren. Beachten Sie, dass diese Slots in dieser Dokumentation nicht behandelt werden, da sie trivial sind, d.h. die meisten von ihnen zeigen nur den Pfad der Aktion im zentralen Widget des Hauptfensters an.

private:
    void createActions();
    void createMenus();

Wir haben uns entschieden, den Konstruktor zu vereinfachen, indem wir zwei private Komfortfunktionen implementieren, um die verschiedenen Aktionen zu erstellen, sie zu Menüs hinzuzufügen und die Menüs in die Menüleiste unseres Hauptfensters einzufügen.

    QMenu *fileMenu;
    QMenu *editMenu;
    QMenu *formatMenu;
    QMenu *helpMenu;
    QActionGroup *alignmentGroup;
    QAction *newAct;
    QAction *openAct;
    QAction *saveAct;
    QAction *printAct;
    QAction *exitAct;
    QAction *undoAct;
    QAction *redoAct;
    QAction *cutAct;
    QAction *copyAct;
    QAction *pasteAct;
    QAction *boldAct;
    QAction *italicAct;
    QAction *leftAlignAct;
    QAction *rightAlignAct;
    QAction *justifyAct;
    QAction *centerAct;
    QAction *setLineSpacingAct;
    QAction *setParagraphSpacingAct;
    QAction *aboutAct;
    QAction *aboutQtAct;
    QLabel *infoLabel;
};

Schließlich deklarieren wir die verschiedenen Menüs und Aktionen sowie ein einfaches Informationsetikett im anwendungsweiten Bereich.

Die Klasse QMenu stellt ein Menü-Widget für die Verwendung in Menüleisten, Kontextmenüs und anderen Popup-Menüs bereit, während die Klasse QAction eine abstrakte Benutzeroberflächenaktion bietet, die in Widgets eingefügt werden kann.

In manchen Situationen ist es sinnvoll, Aktionen zu gruppieren, z. B. wenn wir eine Left Align -Aktion, eine Right Align -Aktion, eine Justify -Aktion und eine Center -Aktion haben und nur eine dieser Aktionen zu einem bestimmten Zeitpunkt aktiv sein soll. Eine einfache Möglichkeit, dies zu erreichen, besteht darin, die Aktionen mit Hilfe der Klasse QActionGroup in einer Aktionsgruppe zusammenzufassen.

Implementierung der MainWindow-Klasse

Im Konstruktor erstellen wir zunächst ein normales QWidget und machen es zum zentralen Widget unseres Hauptfensters. Beachten Sie, dass das Hauptfenster das Eigentum am Widget-Zeiger übernimmt und ihn zu gegebener Zeit löscht.

MainWindow::MainWindow()
{
    QWidget *widget = new QWidget;
    setCentralWidget(widget);

    QWidget *topFiller = new QWidget;
    topFiller->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    infoLabel = new QLabel(tr("<i>Choose a menu option, or right-click to "
                              "invoke a context menu</i>"));
    infoLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
    infoLabel->setAlignment(Qt::AlignCenter);

    QWidget *bottomFiller = new QWidget;
    bottomFiller->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->setContentsMargins(5, 5, 5, 5);
    layout->addWidget(topFiller);
    layout->addWidget(infoLabel);
    layout->addWidget(bottomFiller);
    widget->setLayout(layout);

Dann erstellen wir die Informationsbeschriftung sowie einen oberen und unteren Füller, die wir zu einem Layout hinzufügen, das wir auf dem zentralen Widget installieren. QMainWindow Objekte werden mit ihrem eigenen angepassten Layout geliefert und das Setzen eines Layouts auf das eigentliche Hauptfenster oder das Erstellen eines Layouts mit einem Hauptfenster als Elternteil wird als Fehler betrachtet. Sie sollten stattdessen immer Ihr eigenes Layout für das zentrale Widget festlegen.

    createActions();
    createMenus();

    QString message = tr("A context menu is available by right-clicking");
    statusBar()->showMessage(message);

    setWindowTitle(tr("Menus"));
    setMinimumSize(160, 160);
    resize(480, 320);
}

Um die Aktionen und Menüs zu erstellen, rufen wir unsere beiden Komfortfunktionen auf: createActions() und createMenus(). Wir werden in Kürze auf diese Funktionen zurückkommen.

QMainWindowDie Funktion statusBar() gibt die Statusleiste für das Hauptfenster zurück (wenn die Statusleiste nicht vorhanden ist, erstellt diese Funktion eine leere Statusleiste und gibt sie zurück). Wir initialisieren die Statusleiste und den Fenstertitel, passen die Größe des Fensters an und stellen sicher, dass das Hauptfenster nicht auf eine kleinere Größe als die angegebene Größe verkleinert werden kann.

Schauen wir uns nun die Funktion createActions() genauer an, die die verschiedenen Aktionen erzeugt:

void MainWindow::createActions()
{
    newAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentNew),
                         tr("&New"), this);
    newAct->setShortcuts(QKeySequence::New);
    newAct->setStatusTip(tr("Create a new file"));
    connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
    ...

Ein QAction Objekt kann ein Symbol, einen Text, eine Verknüpfung, einen Statustipp, einen "Was ist das?"-Text und einen Tooltip enthalten. Die meisten dieser Funktionen können im Konstruktor festgelegt werden, aber sie können auch unabhängig davon mit den bereitgestellten Komfortfunktionen festgelegt werden.

In der Funktion createActions() erstellen wir zunächst eine Aktion newAct, wobei wir den Text und ein Symbol mit einer der Konstanten für das Themensymbol übergeben. Mit der Funktion QAction::setShortcut() machen wir Ctrl+N zu seiner Verknüpfung, und mit der Funktion QAction::setStatusTip() setzen wir seinen Statustipp (der Statustipp wird in allen Statusleisten angezeigt, die vom übergeordneten Widget der Aktion bereitgestellt werden). Außerdem verbinden wir das Signal triggered() mit dem Steckplatz newFile().

Die übrigen Aktionen werden auf ähnliche Weise erstellt. Einzelheiten finden Sie im Quellcode.

    alignmentGroup = new QActionGroup(this);
    alignmentGroup->addAction(leftAlignAct);
    alignmentGroup->addAction(rightAlignAct);
    alignmentGroup->addAction(justifyAct);
    alignmentGroup->addAction(centerAct);
    leftAlignAct->setChecked(true);
}

Sobald wir die Aktionen Left Align, Right Align, Justify und Center erstellt haben, können wir auch die zuvor erwähnte Aktionsgruppe erstellen.

Jede Aktion wird der Gruppe mit der Funktion addAction() von QActionGroup hinzugefügt. Beachten Sie, dass eine Aktion auch zu einer Gruppe hinzugefügt werden kann, indem sie mit der Gruppe als Elternteil erstellt wird. Da eine Aktionsgruppe standardmäßig exklusiv ist, wird immer nur eine der Aktionen in der Gruppe geprüft (dies kann mit der Funktion QActionGroup::setExclusive() geändert werden).

Wenn alle Aktionen erstellt sind, verwenden wir die Funktion createMenus(), um die Aktionen zu den Menüs hinzuzufügen und die Menüs in die Menüleiste einzufügen:

void MainWindow::createMenus()
{
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(newAct);
    fileMenu->addAction(openAct);
    fileMenu->addAction(saveAct);
    fileMenu->addAction(printAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    editMenu = menuBar()->addMenu(tr("&Edit"));
    editMenu->addAction(undoAct);
    editMenu->addAction(redoAct);
    editMenu->addSeparator();
    editMenu->addAction(cutAct);
    editMenu->addAction(copyAct);
    editMenu->addAction(pasteAct);
    editMenu->addSeparator();

    helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(aboutAct);
    helpMenu->addAction(aboutQtAct);

QMenuBarDie Funktion addMenu() fügt ein neues QMenu mit dem angegebenen Titel an die Menüleiste an (beachten Sie, dass die Menüleiste das Eigentum an dem Menü übernimmt). Wir verwenden die Funktion QWidget's addAction(), um jede Aktion dem entsprechenden Menü hinzuzufügen.

Alternativ dazu bietet die Klasse QMenu mehrere addAction() Komfortfunktionen, die neue Aktionen aus gegebenen Texten und/oder Symbolen erstellen und hinzufügen. Sie können auch ein Mitglied bereitstellen, das automatisch eine Verbindung zum triggered()-Signal der neuen Aktion herstellt, sowie eine Verknüpfung, die durch eine QKeySequence -Instanz dargestellt wird.

Die Funktion QMenu::addSeparator() erstellt eine neue Trennaktion, d.h. eine Aktion, für die QAction::isSeparator() den Wert true zurückgibt, und fügt die neue Aktion der Liste der Aktionen des Menüs hinzu.

    formatMenu = editMenu->addMenu(tr("&Format"));
    formatMenu->addAction(boldAct);
    formatMenu->addAction(italicAct);
    formatMenu->addSeparator()->setText(tr("Alignment"));
    formatMenu->addAction(leftAlignAct);
    formatMenu->addAction(rightAlignAct);
    formatMenu->addAction(justifyAct);
    formatMenu->addAction(centerAct);
    formatMenu->addSeparator();
    formatMenu->addAction(setLineSpacingAct);
    formatMenu->addAction(setParagraphSpacingAct);
}

Beachten Sie das Menü Format. Erstens wird es mit der Funktion addMenu() von QMenu als Untermenü zum Menü Edit hinzugefügt. Zweitens, sehen Sie sich die Ausrichtungsaktionen an: In der Funktion createActions() haben wir die Aktionen leftAlignAct, rightAlignAct, justifyAct und centerAct zu einer Aktionsgruppe hinzugefügt. Dennoch müssen wir jede Aktion einzeln zum Menü hinzufügen, während die Aktionsgruppe im Hintergrund ihre Arbeit verrichtet.

#ifndef QT_NO_CONTEXTMENU
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu menu(this);
    menu.addAction(cutAct);
    menu.addAction(copyAct);
    menu.addAction(pasteAct);
    menu.exec(event->globalPos());
}
#endif // QT_NO_CONTEXTMENU

Um ein benutzerdefiniertes Kontextmenü bereitzustellen, müssen wir die Funktion contextMenuEvent() von QWidget neu implementieren, um die Kontextmenüereignisse des Widgets zu empfangen (beachten Sie, dass die Standardimplementierung diese Ereignisse einfach ignoriert).

Immer wenn wir ein solches Ereignis erhalten, erstellen wir ein Menü mit den Aktionen Cut, Copy und Paste. Kontextmenüs können entweder asynchron mit der Funktion popup() oder synchron mit der Funktion exec() ausgeführt werden. In diesem Beispiel haben wir uns dafür entschieden, das Menü mit der Funktion exec() anzuzeigen. Indem wir die Position des Ereignisses als Argument übergeben, stellen wir sicher, dass das Kontextmenü an der erwarteten Position erscheint.

Beispielprojekt @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.