本文将围绕 鼠标悬停在 QMenu
上时导致状态栏信息消失 的情况,整合事件信息流,对流程进行详细解读,并通过代码剖析每个关键环节的行为。
1. 问题描述
当鼠标悬停在 QMenu
的空白区域、分隔符或禁用菜单项时:
- 当前的
QAction
被置为nullptr
。 QMenu
调用previousAction->showStatusText("", ...)
,发送空字符串的QStatusTipEvent
。- 状态栏 (
QStatusBar
) 接收到该事件后清空状态栏内容。
修改前
修改后
2. 信息流的完整路径
整个信息流从鼠标事件开始,到状态栏显示或清空结束,共分为以下 5 个阶段:
- 鼠标移动事件触发 (
QMenu
):- 鼠标移动到
QMenu
内部,触发QMenu::mouseMoveEvent
。 - 检测鼠标悬停位置,并调用
QMenuPrivate::setCurrentAction
更新当前QAction
。
- 鼠标移动到
- 当前
QAction
状态更新 (QMenuPrivate
):- 如果鼠标在空白区域,调用
showStatusText("", ...)
,生成空字符串的QStatusTipEvent
。
- 如果鼠标在空白区域,调用
- 状态提示事件发送 (
QActionPrivate
):- 将
QStatusTipEvent
发送到QMainWindow
或父控件。
- 将
- 事件捕获与处理 (
QMainWindow
):QMainWindow::event
捕获QEvent::StatusTip
,并调用QStatusBar::showMessage
。
- 状态栏显示更新 (
QStatusBar
):- 接收到空字符串消息,调用
clearMessage
清空状态栏。
- 接收到空字符串消息,调用
3. 信息流的代码与详细解读
3.1 鼠标移动事件触发
当鼠标移动到 QMenu
内部时,QMenu::mouseMoveEvent
被触发。
核心代码:QMenu::mouseMoveEvent
void QMenu::mouseMoveEvent(QMouseEvent *e) {
Q_D(QMenu);
QAction *action = d->actionAt(e->pos()); // 获取鼠标悬停的 QAction
if ((!action || action->isSeparator()) && !d->sloppyState.enabled()) {
d->setCurrentAction(action); // 鼠标在空白区域,action 为 nullptr
return<