菜单示例
菜单示例演示了如何在主窗口应用程序中使用菜单。
菜单小部件可以是菜单栏中的下拉菜单或独立上下文菜单。下拉菜单在用户单击相应项或按下指定的快捷键时由菜单栏显示。上下文菜单通常通过某些特殊键盘键或通过右键单击来调用。
菜单由一系列 动作 项组成。在应用程序中,许多常见命令可以通过菜单、工具栏按钮以及键盘快捷键来触发。由于用户期望命令以相同的方式执行,而不论使用的是哪种用户界面,因此将每个命令表示为动作是有用的。
菜单示例包含一个单类,MainWindow
,该类继承自 QMainWindow 类。当在应用程序中选择一个动作项时,它将在其中心小部件中显示项的路径。
MainWindow 类定义
QMainWindow 提供了一个主应用程序窗口,其中包含菜单栏、工具栏、停靠小部件以及围绕一个大中心小部件的状态栏。
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: #ifndef QT_NO_CONTEXTMENU void contextMenuEvent(QContextMenuEvent *event) override; #endif // QT_NO_CONTEXTMENU
在这示例中,我们将看到如何实现下拉菜单以及上下文菜单。为了实现自定义上下文菜单,我们必须重写 QWidget 的 contextMenuEvent() 函数以接收主窗口的上下文菜单事件。
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();
我们还必须实现一系列私有槽来响应用户激活我们的任何菜单项。请注意,这些槽尚未在此文档中说明,因为它们是微不足道的,即大多数只需要在主窗口中心小部件中显示动作路径。
private: void createActions(); void createMenus();
我们选择通过实现两个私有便利函数来简化构造函数,这些函数用于创建各种动作、将它们添加到菜单中以及将菜单插入主窗口的菜单栏中。
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; };
最后,我们在全局范围中声明了各种菜单、动作以及一个简单的信息标签。
QMenu 类为菜单栏、上下文菜单和其他弹出式菜单提供了一个菜单小部件,而 QAction 类提供了一个抽象的用户界面动作,该动作可以插入到小部件中。
在某些情况下,将动作分组在一起是有用的,例如,我们有一个 左对齐 动作、一个 右对齐 动作、一个 两端对齐 动作和一个 居中 动作,并且我们只想在任何时候激活这些动作中的一个。实现此目的的一种简单方法是用 QActionGroup 类将动作组合在一起。
MainWindow 类实现
在构造函数中,我们首先创建一个普通的 QWidget 并将其设为我们的主窗口的中央部件。请注意,主窗口将接管部件指针的拥有权并在适当的时间删除它。
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);
然后,我们创建了信息标签,以及一些顶部和底部的填充部件,我们将这些添加到一个布局中,并将该布局安装到中央部件上。 QMainWindow 对象自带自己的自定义布局,在主窗口上设置布局或以主窗口为父创建布局会被认为是错误的。您应该在中央部件上设置自己的布局。
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); }
要创建操作和菜单,我们调用了我们的两个便利函数: createActions()
和 createMenus()
。我们稍后会回到这些。
QMainWindow 的 statusBar() 函数返回主窗口的状态栏(如果状态栏不存在,此函数将创建并返回一个空的状态栏)。我们初始化状态栏和窗口标题,将窗口调整到合适的大小,并确保主窗口不能调整到小于给定的大小。
现在,让我们更仔细地看看创建各种操作的便利函数 createActions()
。
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); ...
QAction 对象可以包含一个图标、文本、快捷键、状态提示、"这是什么?" 文本和工具提示。其中大部分可以在构造函数中设置,但也可以通过提供的便利函数独立设置。
在 createActions()
函数中,我们首先创建一个 newAct
操作,通过使用主题图标常量传递文本和图标。我们使用 QAction::setShortcut() 函数将其快捷键设为 Ctrl+N,并使用 QAction::setStatusTip() 函数设置其状态提示(状态提示在操作的最顶层父部件提供的状态栏上显示)。我们还将其 triggered() 信号连接到 newFile()
插槽。
其余的操作以类似的方式创建。请参阅源代码以获取详细信息。
alignmentGroup = new QActionGroup(this); alignmentGroup->addAction(leftAlignAct); alignmentGroup->addAction(rightAlignAct); alignmentGroup->addAction(justifyAct); alignmentGroup->addAction(centerAct); leftAlignAct->setChecked(true); }
创建完 左对齐、右对齐、居中对齐 和一个 居中 操作后,我们还可以创建之前提到的操作组。
使用 QActionGroup 的 addAction() 函数将每个操作添加到组中。请注意,操作也可以通过将组设置为父对象时创建来添加到组中。由于操作组默认是排他的,因此在该组中任何时候只有一个操作被选中(这可以通过 QActionGroup::setExclusive() 函数来更改)。
创建所有操作后,我们使用 createMenus()
函数将操作添加到菜单,并将菜单插入到菜单栏中
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);
QMenuBar 的 addMenu() 函数将给定标题的新 QMenu 追加到菜单栏(注意,菜单栏接管菜单的拥有权)。我们使用 QWidget 的 addAction() 函数将每个操作添加到相应的菜单。
或者,QMenu 类提供了几个 addAction() 便利函数,这些函数可以创建并添加从给定的文本和/或图标中新的操作。您还可以提供成员,此成员将自动连接到新操作的 triggered() 信号,以及一个由 QKeySequence 实例表示的快捷键。
函数 QMenu::addSeparator() 创建并返回一个新的分隔符操作,即对于该操作,QAction::isSeparator() 返回 true,并将新操作添加到菜单的操作列表中。
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); }
注意“格式”菜单。首先,它是通过使用 QMenu 的 addMenu() 函数作为“编辑”菜单的子菜单添加的。其次,看看对齐操作:在 createActions()
函数中,我们将 leftAlignAct
、rightAlignAct
、justifyAct
和 centerAct
操作添加到操作组中。尽管如此,在操作组在幕后进行魔术处理的同时,我们必须将每个操作单独添加到菜单中。
#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
要提供一个自定义上下文菜单,我们必须重新实现 QWidget 的 contextMenuEvent() 函数以接收小部件的上下文菜单事件(注意,默认实现简单地忽略了这些事件)。
每次接收到此类事件时,我们都会创建一个包含 剪切、复制 和 粘贴 操作的菜单。可以使用 popup() 函数异步执行上下文菜单或使用 exec() 函数同步执行。在本例中,我们选择了使用其 exec() 函数来显示菜单。通过传递事件的位置作为参数,我们确保上下文菜单出现在预期位置。
© 2024 Qt 公司有限公司。本文档中包含的文档贡献是各自所有者的版权。本文档是根据自由软件基金会发布并由其使用的 GNU 自由文档许可版本 1.3 许可的。Qt 及其相关标志是芬兰及/或其他国家/地区的 Qt 公司的商标。所有其他商标均为各自所有者的财产。