此篇文章来源于自己在学习QT的QMenu过程当中所总结的知识点,本人能力有限,欢迎大家评论区评论,共同学习,共同进步。
一、QMenu介绍
QMenu
是Qt库中用于创建弹出式菜单的类,它通常出现在应用程序的顶部菜单栏、按钮的右键菜单或自定义上下文菜单中。QMenu
类提供了一系列方法来添加菜单项、子菜单以及关联槽函数,以便在用户选择菜单项时执行相应的动作。
主要特性包括:
构造函数:通过
QMenu(QString title, QWidget *parent = nullptr)
创建带有标题的菜单,父窗口用于确定菜单所在的上下文。添加菜单项:
addAction(QAction *)
:添加一个QAction
对象到菜单中。addMenu(QMenu *)
:添加一个子菜单到当前菜单。addSeparator()
:在菜单中添加一个分隔线,用于区分不同的菜单项组。事件处理:
- 通过关联槽函数到
triggered(QAction *)
信号,可以在用户选择菜单项时执行相应操作。显示菜单:
- 使用
exec(QPoint globalPos)
弹出菜单并等待用户选择一个项,然后返回被选中项的 QAction 对象指针。- 或者,使用
popup(QPoint pos)
直接在指定的位置弹出菜单,不阻塞程序执行。
示例代码:
QMenu* menu = new QMenu(tr("File"), this);
// 添加菜单项
QAction* actionOpen = new QAction(tr("&Open"), this);
menu->addAction(actionOpen);
// 添加子菜单
QMenu* submenu = new QMenu(tr("Submenu"));
submenu->addAction(tr("SubMenu Item"));
menu->addMenu(submenu);
// 连接槽函数
connect(actionOpen, &QAction::triggered, this, &YourClass::onOpenActionTriggered);
// 弹出菜单
menu->popup(mapToGlobal(pos));
在上述示例中,我们创建了一个名为 "File" 的菜单,并添加了一个名为 "Open" 的菜单项以及一个名为 "Submenu" 的子菜单。还连接了 "Open" 菜单项的触发信号到一个槽函数,以便在用户点击该菜单项时执行相应的操作。最后,我们在指定位置弹出了菜单。
二、成员函数
1、QMenu::QMenu(const QString &title, QWidget *parent = nullptr)
QMenu::QMenu(const QString &title, QWidget *parent = nullptr)
是 QMenu
类的一个构造函数,用于创建一个新的 QMenu
对象。
参数说明:
const QString &title
: 这是菜单的标题,它将以文本形式显示在菜单的顶部,帮助用户识别菜单的目的或功能。
QWidget *parent = nullptr
: 这是指向QWidget
类型的指针,表示QMenu
对象的父窗口。如果提供了父窗口,那么该菜单将与其父窗口在视觉和事件处理方面相关联。如果没有提供父窗口(默认值nullptr
),菜单仍可正常工作,但可能在某些上下文中无法正确地与用户界面集成。
示例代码:
// 创建一个标题为 "File" 的菜单,其父窗口为 MainWindow
QMainWindow *mainWindow = new QMainWindow();
QMenu *fileMenu = new QMenu("File", mainWindow);
// 添加菜单项
fileMenu->addAction("Open");
fileMenu->addAction("Save");
fileMenu->addSeparator();
fileMenu->addAction("Exit");
// 将菜单添加到主窗口的菜单栏中
mainWindow->menuBar()->addMenu(fileMenu);
在上述示例中,我们创建了一个标题为 "File" 的 QMenu
对象,并将其父窗口设置为 mainWindow
。然后,我们向菜单中添加了几个动作(菜单项),最后将该菜单添加到了主窗口的菜单栏中。
2、QMenu::QMenu(QWidget *parent = nullptr)
QMenu::QMenu(QWidget *parent = nullptr)
是 QMenu
类的一个构造函数,用于创建一个不带标题的 QMenu
对象。
参数说明:
QWidget *parent = nullptr
: 这是指向QWidget
类型的指针,表示QMenu
对象的父窗口。如果提供了父窗口,那么该菜单将与其父窗口在视觉和事件处理方面相关联。例如,菜单的样式可能继承自其父窗口的样式表,菜单的生命周期也会受其父窗口生命周期的影响。如果未提供父窗口(默认值nullptr
),菜单仍可正常工作,但在某些上下文中可能无法正确地与用户界面集成。
示例代码:
// 创建一个无标题的菜单,其父窗口为 MainWindow
QMainWindow *mainWindow = new QMainWindow();
QMenu *contextMenu = new QMenu(mainWindow);
// 添加菜单项
contextMenu->addAction("Cut");
contextMenu->addAction("Copy");
contextMenu->addAction("Paste");
// 将菜单关联到某个组件的右键菜单
QPushButton *button = new QPushButton("Right Click Me", mainWindow);
button->setContextMenuPolicy(Qt::CustomContextMenu);
connect(button, &QPushButton::customContextMenuRequested, [contextMenu](const QPoint &pos){
contextMenu->exec(button->mapToGlobal(pos));
});
在上述示例中,我们创建了一个无标题的 QMenu
对象,并将其父窗口设置为 mainWindow
。然后,我们向菜单中添加了一些动作(菜单项),最后将这个菜单关联到了一个按钮的右键菜单事件。当用户在该按钮上右击时,将弹出我们创建的菜单。
3、void QMenu::aboutToHide()
void QMenu::aboutToHide()
是 QMenu
类的一个信号(signal),而不是一个函数。当 QMenu
即将关闭并隐藏时,这个信号会被发射。开发者可以连接(connect)到这个信号来执行在菜单隐藏前需要做的某些操作。
示例代码:
QMenu *menu = new QMenu(this);
connect(menu, &QMenu::aboutToHide, this, [this]() {
qDebug() << "Menu is about to hide.";
// 在这里添加在菜单隐藏前需要执行的操作
});
在上述代码中,当 menu
即将隐藏时,会打印一条消息并执行自定义的代码块。这个信号可以用于跟踪用户何时关闭了菜单,进而进行诸如保存状态、更新界面、恢复焦点等操作。
4、void QMenu::aboutToShow()
void QMenu::aboutToShow()
是 QMenu
类的一个信号(signal),当 QMenu
即将显示时,这个信号会被发射。开发者可以连接(connect)到这个信号来执行在菜单显示前需要做的某些操作,例如动态填充菜单内容或更新菜单的状态。
示例代码:
QMenu *menu = new QMenu(this);
connect(menu, &QMenu::aboutToShow, this, [this]() {
qDebug() << "Menu is about to show.";
// 在这里添加在菜单显示前需要执行的操作,例如:
// 动态生成或更新菜单项
QAction *action = menu->addAction("New Action");
});
// 通过某个控件(如按钮)显示菜单
QPushButton *button = new QPushButton("Show Menu", this);
connect(button, &QPushButton::clicked, [menu]() {
menu->popup(button->mapToGlobal(QPoint(0, button->height())));
});
在上述代码中,当点击按钮并即将弹出 menu
时,aboutToShow()
信号会被触发,并打印一条消息。同时,你可以在信号槽(slot)中添加代码来动态地生成或更新菜单项。
5、void QMenu::hovered(QAction *action)
void QMenu::hovered(QAction *action)
是Qt框架中的一个信号(signal),这个信号会在用户鼠标光标悬停在菜单(QMenu)中的某个动作(QAction)上时发出。
当用户将鼠标移动到菜单项(即QAction对象所代表的菜单选项)上方但未点击时,hovered()
信号就会被触发,并将当前被鼠标光标悬浮在其上的QAction对象作为参数传递给连接此信号的槽函数(slot)。开发者可以监听这个信号来实现特定功能,比如预览或动态更新相关信息等。
简单来说:
// 当鼠标悬停在菜单项上时触发的信号
void hovered(QAction *action);
意味着每当用户的鼠标悬停在一个菜单项上时,会有一个通知发送出去,通知中包含了当前被悬停的菜单项的指针。开发人员可以通过关联这个信号到相应的处理函数来响应这一事件。
6、void QMenu::triggered(QAction *action)
void QMenu::triggered(QAction *action)
同样是Qt框架中的一个信号,当用户在菜单(QMenu)中选择并触发了一个动作(QAction),例如点击了菜单项时,该信号会被发射。
具体来说:
这个信号在用户实际点击并执行了菜单中的某一项操作时发出,它会将被触发的QAction对象作为参数传递给连接此信号的槽函数。通过监听和处理这个信号,开发者可以得知用户具体选择了哪个菜单项,并根据不同的QAction对象执行相应的操作或逻辑。
#include <QMainWindow>
#include <QMenu>
#include <QAction>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
// 创建一个动作
QAction *actionOpen = new QAction(tr("打开"), this);
QAction *actionSave = new QAction(tr("保存"), this);
// 创建一个菜单
QMenu *fileMenu = menuBar()->addMenu(tr("&文件"));
// 将动作添加到菜单
fileMenu->addAction(actionOpen);
fileMenu->addAction(actionSave);
// 连接触发信号与槽函数
connect(actionOpen, &QAction::triggered, this, &MainWindow::onOpenTriggered);
connect(actionSave, &QAction::triggered, this, &MainWindow::onSaveTriggered);
// 连接悬停信号与槽函数(假设你想要对悬停行为进行处理)
connect(fileMenu, &QMenu::hovered, this, &MainWindow::onActionHovered);
}
private slots:
// 当“打开”菜单项被触发时的槽函数
void onOpenTriggered()
{
qDebug() << "打开菜单项被点击";
// 在这里实现打开文件的功能
}
// 当“保存”菜单项被触发时的槽函数
void onSaveTriggered()
{
qDebug() << "保存菜单项被点击";
// 在这里实现保存文件的功能
}
// 当任意菜单项被鼠标悬停时的槽函数
void onActionHovered(QAction *action)
{
QString message = QStringLiteral("鼠标悬停在了 '%1' 菜单项上");
qDebug() << message.arg(action->text());
// 在这里实现鼠标悬停时的行为,如预览、提示等
}
};
7、QMenu::~QMenu()
QMenu::~QMenu()
是C++中QMenu类的一个析构函数。在面向对象编程中,析构函数是一种特殊的方法,主要负责释放对象占用的资源,清理工作,以及在对象生命周期结束时进行必要的“善后”工作。
对于Qt的QMenu
类来说,~QMenu()
析构函数会在QMenu对象不再被使用并且其引用计数降为0时自动调用。在这个过程中,Qt框架会清理与该菜单关联的所有资源,包括但不限于释放内存、关闭任何打开的系统资源(如关联的窗口句柄等)以及其他内部数据结构的清理工作。
简而言之,当你创建的QMenu对象不再需要且超出其作用范围时,系统会自动调用~QMenu()
析构函数来确保相关资源得到妥善释放。
8、QAction *QMenu::actionAt(const QPoint &pt) const
QAction *QMenu::actionAt(const QPoint &pt) const
是Qt库中QMenu类的一个成员函数。这个函数的作用是在给定的坐标点(const QPoint &pt
)查找其所对应的QAction对象。
参数 pt
是一个二维坐标点,通常表示屏幕坐标系下的位置。当你调用这个函数并传入一个坐标点时,QMenu会检查该点是否位于其任何一个子菜单项(QAction)上,如果找到了,则返回指向该QAction对象的指针;如果没有找到则返回nullptr。
举例说明,如果你知道鼠标的当前位置,并想判断该位置下是否有菜单项被覆盖,就可以使用这个函数来获取对应位置的QAction对象。这对于实现某些自定义交互效果或者调试非常有用。
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QPoint>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
window.setWindowTitle("QMenu Example");
// 创建菜单栏
QMenuBar *menuBar = window.menuBar();
// 创建一个菜单
QMenu *fileMenu = new QMenu("File");
menuBar->addMenu(fileMenu);
// 创建两个菜单项
QAction *actionOpen = new QAction("Open", &window);
QAction *actionSave = new QAction("Save", &window);
fileMenu->addAction(actionOpen);
fileMenu->addAction(actionSave);
// 假设我们有一个鼠标位置
QPoint mousePos(100, 200); // 这个位置应根据实际情况获取,此处仅为示例
// 获取鼠标位置下的QAction
QAction *actionUnderCursor = fileMenu->actionAt(mousePos);
if (actionUnderCursor) {
qDebug() << "The action under the cursor is: " << actionUnderCursor->text();
} else {
qDebug() << "No action is found at the given position.";
}
// 显示主窗口
window.show();
return app.exec();
}
这段代码首先创建了一个包含两个菜单项("Open"和"Save")的菜单。然后,它模拟了一个鼠标位置(mousePos
),并通过调用 QMenu::actionAt()
来尝试获取该位置下的QAction。最后,输出结果表明该位置是否包含一个菜单项及其文本内容。然而,在实际应用中,你需要替换 mousePos
的值为实时的鼠标屏幕坐标。
9、void QMenu::actionEvent(QActionEvent *e)
void QMenu::actionEvent(QActionEvent *e)
是Qt框架中QMenu类的一个重载函数,主要用于处理与QAction相关的事件。QActionEvent是对QAction(菜单项)状态或属性改变的通知,这些事件可能包括动作的添加、移除、启用、禁用等。
当QMenu中的QAction发生状态更改时,QApplication会生成一个QActionEvent并将其发送给QMenu。此时,QMenu的actionEvent()
函数就会被调用,以便让QMenu有机会对此事件作出反应。
在自定义QMenu类的子类时,你可以重写这个函数以处理特定的QAction事件,例如:
void MyCustomMenu::actionEvent(QActionEvent *e)
{
switch (e->type()) {
case QEvent::ActionAdded:
qDebug() << "An action has been added to the menu:" << e->action()->text();
break;
case QEvent::ActionRemoved:
qDebug() << "An action has been removed from the menu:" << e->action()->text();
break;
case QEvent::ActionChanged:
qDebug() << "An action in the menu has changed:" << e->action()->text();
break;
default:
break;
}
// 调用父类的实现以保持默认行为
QMenu::actionEvent(e);
}
以上代码只是一个示例,展示了如何在动作添加、移除或改变时打印出相关信息。在实际项目中,你可以根据需要编写自己的处理逻辑。
10、QRect QMenu::actionGeometry(QAction *act) const
QRect QMenu::actionGeometry(QAction *act) const
是Qt GUI库中QMenu类的一个成员函数。该函数用于获取与指定QAction关联的矩形区域几何信息,即该动作在菜单中显示时所占据的空间位置和尺寸。
当你想要知道某个QAction在QMenu上具体的位置和大小时,可以调用此函数,它将返回一个QRect对象,该对象包含了QAction在菜单视图坐标系下的左上角坐标(x,y)以及宽度和高度。
使用示例:
QAction *myAction = menuBar->findChild<QAction*>("myAction");
if (myAction) {
QRect rect = menu->actionGeometry(myAction);
int x = rect.x();
int y = rect.y();
int width = rect.width();
int height = rect.height();
qDebug() << "Action Geometry: (" << x << ", " << y << ") - Size: (" << width << ", " << height << ")";
}
请注意,在上述代码中,“menu”应替换为你的QMenu实例指针,而“myAction”是你要查询其几何信息的QAction实例的名称或指针。通过这种方式,你可以获取到指定QAction在显示菜单时的具体布局位置和大小信息。
11、QAction *QMenu::activeAction() const
QAction *QMenu::activeAction() const
是Qt框架中QMenu类的一个成员函数,用于获取当前激活(active)的动作(QAction)。在菜单(QMenu)中,激活的动作通常指的是用户最近一次点击或者通过键盘导航选定的动作。
返回值类型为QAction指针,如果当前没有激活的动作,则返回NULL(在C++11之后版本中为nullptr)。
这个函数常用于确定用户当前在菜单中选中的项,或者在实现一些特定交互逻辑时需要用到当前激活动作的状态。例如,如果你的应用程序需要跟踪用户在菜单中选择的最后一个动作,就可以使用这个函数。
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
// 创建菜单栏和菜单
QMenuBar *menuBar = new QMenuBar(this);
setMenuBar(menuBar);
QMenu *fileMenu = new QMenu("File", this);
menuBar->addMenu(fileMenu);
// 添加两个动作到菜单
QAction *openAction = new QAction("Open", this);
QAction *saveAction = new QAction("Save", this);
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
// 监听菜单激活动作的变化
connect(fileMenu, &QMenu::aboutToShow, this, [=](){
qDebug() << "Before showing menu, active action is: " << fileMenu->activeAction();
});
connect(fileMenu, &QMenu::triggered, this, [=](QAction *action){
qDebug() << "Action triggered: " << action->text();
qDebug() << "After triggering, active action is: " << fileMenu->activeAction();
});
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
在这个例子中,我们在菜单显示前和动作触发后都打印了当前激活的动作。实际上,在菜单显示时,如果没有之前激活的动作,activeAction()
往往会返回 nullptr。而在用户点击菜单项后,triggered
信号触发时,activeAction()
应该返回刚刚被点击的那个动作。不过,菜单关闭后,activeAction()
又会变回 nullptr,除非你手动设置一个持续的激活动作。
12、QAction *QMenu::addAction(const QString &text)
QAction *QMenu::addAction(const QString &text)
是Qt库中QMenu类的一个成员函数。这个函数用于向QMenu对象添加一个新的QAction,该QAction带有指定的文本(text)。
函数签名中的 const QString &text
参数是要添加到菜单中的新动作的文本标签。当你调用此函数时,它会创建一个新的QAction对象,并将其添加到菜单的末尾,同时返回指向新创建的QAction对象的指针。
以下是一个简单的使用示例:
QMenu *myMenu = new QMenu("My Menu"); // 创建一个名为"My Menu"的菜单
// 使用addAction添加两个动作
QAction *action1 = myMenu->addAction("Action 1");
QAction *action2 = myMenu->addAction("Action 2");
// 你可以进一步配置这些动作,例如关联槽函数、设置快捷键等
connect(action1, &QAction::tr