如上图,我们创建了一个搜索栏,添加了一个带有图标的动作,然后你可能会想将鼠标移动到这个图标上面时让这个图标变色,首先,我需要回忆一下Qt的信号和槽机制。QAction有hovered信号,但可能没有直接的“离开”信号。也就是说,当鼠标进入动作时会触发hovered。给出如下代码:
连接 hovered 信号
connect(searchAction, &QAction::hovered, this, [=]() {
searchAction->setIcon(QIcon(":/Res/menuIcon/search-blue.svg")); // 设置为手形指针
});
在代码中,用户连接了hovered信号,当鼠标悬停在动作上时,图标变成蓝色。刚开始可能会以为成功了,实则不然。在鼠标移出该图标时,图标仍然为蓝色。。。该怎么办呢?
这时候可能需要用到QWidget的enterEvent和leaveEvent,或者考虑使用事件过滤器来捕捉鼠标的进入和离开事件。
不过,QAction本身并不是QWidget的子类,所以不能直接处理鼠标事件。那怎么办呢?可能应该查找与QAction相关联的控件,比如QToolButton,因为QLineEdit添加的QAction通常会有一个内部的QToolButton来实现显示。
当将QAction添加到QLineEdit时,QLineEdit会为这个动作创建一个QToolButton作为它的子控件。这时候可以尝试获取这个按钮,然后监听它的enter和leave事件,或者使用样式表来改变图标的状态。
或者,考虑使用事件过滤器,监控QLineEdit的QAction的位置,当鼠标移动到该区域之外时,恢复图标。但这样可能比较复杂。
另一个思路是,当鼠标进入QAction时改变图标,当离开时恢复。但QAction本身可能不提供离开的信号,所以可能需要通过事件过滤器来监听鼠标离开事件。
具体步骤可能是这样的:首先,获取QAction对应的widget,也就是那个按钮。可以通过QLineEdit的findChild方法查找QToolButton,或者遍历子控件。找到对应的QToolButton之后,安装事件过滤器到该按钮,然后在事件过滤器中处理鼠标进入和离开的事件,改变图标。
或者,使用样式表来设置不同状态下的图标。例如,设置按钮的hover状态图标为蓝色,普通状态为黑色。这样可能更简单,不需要编写额外的代码。
但用户使用的是QAction的图标,可能样式表的方法需要针对具体的按钮设置。或者,如果QAction的图标设置是通过样式表的话,可能需要调整。不过用户目前是在代码中直接设置图标,所以可能需要另一种方式。
例如,当QToolButton的hover状态改变时,自动切换图标。或者,直接使用QToolButton的setIcon方法,并在事件过滤器中处理enter和leave事件。
所以,可能的解决方案是:
-
获取QAction对应的QToolButton
使用findChildren
遍历QLineEdit的子控件,找到关联的QToolButton。 -
安装事件过滤器
监听按钮的鼠标进入和离开事件。 -
处理事件切换图标
在事件过滤器中根据事件类型切换图标。
那具体如何实现呢?代码入下:
// 搜索栏设置
ui->search_lineEdit->setPlaceholderText(QStringLiteral("搜索"));
ui->search_lineEdit->setFixedWidth(200); // 使用 fixedWidth 正确设置宽度
// 创建动作并设置图标
const auto searchAction = new QAction(QIcon(":/Res/menuIcon/search-black.svg"), "搜索", ui->search_lineEdit);
ui->search_lineEdit->addAction(searchAction, QLineEdit::TrailingPosition);
// 获取关联的QToolButton
QToolButton* searchButton = nullptr;
foreach (QToolButton* btn, ui->search_lineEdit->findChildren<QToolButton*>()) {
if (btn->defaultAction() == searchAction) {
searchButton = btn;
break;
}
}
// 安装事件过滤器
if (searchButton) {
searchButton->installEventFilter(this);
}
// 在类头文件中声明 eventFilter 函数
// protected:
// bool eventFilter(QObject *watched, QEvent *event) override;
// 实现事件过滤器
bool YourClass::eventFilter(QObject* watched, QEvent* event) {
QToolButton* button = qobject_cast<QToolButton*>(watched);
if (button && button->defaultAction() == searchAction) {
if (event->type() == QEvent::Enter) {
searchAction->setIcon(QIcon(":/Res/menuIcon/search-blue.svg"));
} else if (event->type() == QEvent::Leave) {
searchAction->setIcon(QIcon(":/Res/menuIcon/search-black.svg"));
}
}
return QObject::eventFilter(watched, event);
}
代码解释:
-
使用
findChildren
查找QLineEdit中所有QToolButton,通过比较defaultAction
确认目标按钮。 -
通过事件过滤器监听按钮的
QEvent::Enter
(鼠标进入)和QEvent::Leave
(鼠标离开)事件。 -
在事件处理中切换图标,实现悬停变色效果。
这样即可在鼠标移入时显示蓝色图标,移出时恢复黑色图标。