1、前言
在Qt中实现导航按钮事件通常涉及信号与槽机制、事件处理或QAction的触发。以下是几种常见实现方式:
- 使用QPushButton的clicked信号
- 通过QAction实现快捷键导航
- 重写事件过滤器处理特定按键
- 在QML中实现导航按钮
- 使用QTabWidget实现页面导航
对于复杂导航场景,可结合QStackedWidget管理多个页面,通过按钮信号切换当前显示的页面。在移动端开发中,滑动手势识别也可作为导航事件的补充方式。
2、动手干
1、添加事件函数
paintEvent 概述
paintEvent 是 Qt 框架中用于处理窗口部件(Widget)绘制事件的核心虚函数。当部件需要重绘时(如窗口首次显示、大小调整、部分区域暴露等),系统会自动调用此函数。开发者需重写此函数以实现自定义绘制逻辑。通过合理使用 paintEvent,可以实现复杂的自定义界面绘制,同时保持高效和稳定。
基本用法
在自定义的 QWidget 子类中重写 paintEvent 方法,使用 QPainter 进行绘图操作:
cpp
void MyWidget::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.setPen(Qt::blue);
painter.drawRect(10, 10, 100, 50);
}
关键注意事项
避免直接调用 paintEvent
应通过 update() 或 repaint() 触发重绘。update() 是异步的,会合并多次请求;repaint() 是同步的,立即重绘但可能影响性能。
mousePressEvent 概述
mousePressEvent 是 Qt 框架中 QWidget 及其子类的一个事件处理函数,用于响应鼠标按键按下事件。通常在自定义控件或窗口时重写此函数以实现交互逻辑。
基本用法
在继承自 QWidget 的类中重写 mousePressEvent,通过判断事件参数(QMouseEvent)的属性和方法来处理鼠标按下动作:
cpp
void MyWidget::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
// 左键按下逻辑
} else if (event->button() == Qt::RightButton) {
// 右键按下逻辑
}
event->accept(); // 标记事件已处理
}
关键参数解析
event->button()
返回触发事件的鼠标按键(如Qt::LeftButton、Qt::RightButton)。event->pos()
返回鼠标相对于当前控件的坐标(QPoint类型)。event->globalPos()
返回鼠标在屏幕全局坐标系中的坐标。
注意事项
- 若需处理其他鼠标事件(如释放或移动),需同时重写
mouseReleaseEvent和mouseMoveEvent。 - 在 Qt 中,事件处理函数的默认实现可能包含必要逻辑(如父类调用),通常建议保留默认行为
enterEvent 的概念
enterEvent 是 Qt 框架中的一个事件类型,当鼠标光标进入某个控件的边界时触发。该事件常用于实现鼠标悬停效果、动态 UI 交互或状态提示。
基本用法
在自定义控件中重写 enterEvent 方法,即可响应鼠标进入事件。以下是一个 PyQt5 的示例代码:
cpp
from PyQt5.QtWidgets import QWidget, QLabel
from PyQt5.QtCore import Qt
class HoverWidget(QWidget):
def __init__(self):
super().__init__()
self.label = QLabel("Hover over me!", self)
self.label.setAlignment(Qt.AlignCenter)
def enterEvent(self, event):
self.label.setText("Mouse entered!")
self.setStyleSheet("background-color: lightblue;")
def leaveEvent(self, event):
self.label.setText("Mouse left!")
self.setStyleSheet("background-color: white;")
关键注意事项
- 事件对象 :
enterEvent的参数event是QEvent类型,包含事件的基本信息(如时间戳)。 - 与
leaveEvent配对 :通常需要同时重写leaveEvent以实现完整的悬停效果。 - 样式控制 :可通过
setStyleSheet动态修改控件样式,增强视觉反馈。
leaveEvent 概述
在 Qt 中,leaveEvent 是一个事件处理函数,用于处理当鼠标光标离开某个控件(QWidget)时触发的事件。它是 QWidget 类的一个虚函数,可以通过重写该函数来自定义控件在鼠标离开时的行为。
使用场景
leaveEvent 常用于以下场景:
- 当鼠标离开控件时,改变控件的样式或状态(例如高亮或取消高亮)。
- 触发某些逻辑,例如隐藏提示信息或停止动画。
cpp
#include <QWidget>
#include <QEvent>
#include <QDebug>
class MyWidget : public QWidget {
public:
MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}
protected:
void leaveEvent(QEvent *event) override {
qDebug() << "Mouse left the widget";
// 可以在这里添加自定义逻辑
QWidget::leaveEvent(event); // 调用基类实现(可选)
}
};
注意事项
leaveEvent是一个受保护函数,只能在继承QWidget的子类中重写。- 如果需要调用基类的实现(例如
QWidget::leaveEvent),可以在重写函数中显式调用,但通常这不是必须的。 leaveEvent与enterEvent是成对的,分别处理鼠标进入和离开控件的事件。
完整代码
cpp
#ifndef NAVBUTTON_H
#define NAVBUTTON_H
#include <QPaintEvent>
#include <QWidget>
class NavButton : public QWidget
{
Q_OBJECT
Q_PROPERTY(int icon READ icon WRITE setIcon);
Q_PROPERTY(QString text READ text WRITE setText);
Q_PROPERTY(bool isChecked READ isChecked WRITE setIsChecked);
public:
explicit NavButton(QWidget *parent = nullptr);
int icon() const{
return m_icon;
}
QString text() const
{
return m_text;
}
bool isChecked() const
{
return m_isChecked;
}
public slots:
void setIcon(int icon)
{
if(m_icon==icon) return;
m_icon = icon;
// 涉及到控件的重绘
update();
}
void setText(QString text)
{
m_text = text;
}
void setIsChecked(bool isChecked)
{
m_isChecked = isChecked;
update();//控件重绘
}
private:
bool isMouseOver=false;
int m_icon;
QString m_text;
bool m_isChecked;
bool m_isEnter=false;//鼠标是否进入的标志
protected:
void paintEvent(QPaintEvent *event) override;//窗体重绘事件
void mousePressEvent(QMouseEvent *event) override;//鼠标按下事件
void enterEvent(QEnterEvent *event) override;//鼠标已进入事件
void leaveEvent(QEvent *event) override;//鼠标未进入事件
signals:
};
#endif // NAVBUTTON_H
2、编写事件代码


完整代码
cpp
#include "navbutton.h"
#include <QPaintEvent>
#include <QPainter>
NavButton::NavButton(QWidget *parent): QWidget{parent}
{
}
//窗体重绘事件
void NavButton::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QColor(0,0,0,0));
//1、绘制按钮的背景
if(m_isChecked){//如果选中,则设置线性渐变
//创建渐变对象
QLinearGradient gradient(0,0,this->rect().width(),this->rect().height());//从哪开始进行渐变,0,0是起点,终点是矩形的宽度和高度
gradient.setColorAt(0,QColor(62,155,253));//起点颜色
gradient.setColorAt(1,QColor(33,97,216));//终点颜色
painter.setBrush(gradient); //设置笔刷
}
else{//非选中状态
if(m_isEnter){//鼠标已进入时
painter.setBrush(QColor(255,255,255,60));
}else{//鼠标未进入时
painter.setBrush(QColor(0,0,0,0));
}
}
painter.drawRoundedRect(this->rect(),10,10);//绘制带有圆角的矩形,10是圆角半径
//2、绘制图标
if(m_isChecked){//已选中
painter.setPen(QColor(255,255,255));//设置笔的颜色
}else{//未选中
painter.setPen(QColor(255,255,255,90));
}
QFont iconFont=QFont("zx_icons",22);//创建字体对象
painter.setFont(iconFont);//设置字体
//参数1表示位置 ,参数2表示对齐方式,参数3表示文字内容
painter.drawText(QRect(0,10,this->rect().width(),this->rect().height()),
Qt::AlignHCenter,
QChar(this->icon()));
//3、绘制标题
QFont font=QFont("Microsoft YaHei",9);
painter.setFont(font);
painter.drawText(QRect(0,10,this->rect().width(),this->rect().height()-22),
Qt::AlignHCenter|Qt::AlignBottom,
this->text());
//4、绘制线边框
if(m_isChecked){
QPen pen(QColor(255,150,0),3);
painter.setPen(pen);
painter.drawLine(2,10,2,this->rect().height()-10);
}
}
//鼠标按下事件
void NavButton::mousePressEvent(QMouseEvent *event)
{
//遍历被点击控件的父级控件的所有子控件
foreach (auto item, this->parent()->children()) {
if(item->inherits("NavButton")){//如果这个控件继承自"NavButton"类则处理
dynamic_cast<NavButton*>(item)->setIsChecked(false);//将该控件强制转换成NavButton,并且设置isChecked属性为false,即不选中
}
}
this->setIsChecked(true);//设置自己为选中
}
//鼠标已进入事件
void NavButton::enterEvent(QEnterEvent *event)
{
m_isEnter=true;
update();
}
//鼠标未进入事件
void NavButton::leaveEvent(QEvent *event)
{
m_isEnter=false;
update();
}
QPainter 概述
QPainter 是 Qt 框架中用于执行绘图操作的核心类,支持在多种绘图设备(如 QWidget、QPixmap、QImage 等)上绘制 2D 图形、文本和图像。它提供了丰富的绘图功能,包括基本形状绘制、路径操作、坐标变换、混合模式等。
基本用法
QPainter 通常与绘图设备一起使用,通过构造函数或 begin() 方法绑定设备
常用功能
绘制基本图形
- 线条:
drawLine() - 矩形:
drawRect() - 椭圆/圆:
drawEllipse() - 多边形:
drawPolygon()
设置画笔与画刷
- 画笔(轮廓):
setPen(QPen),控制线条颜色、宽度和样式。 - 画刷(填充):
setBrush(QBrush),控制填充颜色或纹理。
坐标变换
- 平移:
translate(dx, dy) - 缩放:
scale(sx, sy) - 旋转:
rotate(angle)
文本绘制
drawText()用于绘制文本,支持字体设置(setFont())和对齐方式。
注意事项
- QPainter 必须在有效的绘图设备上操作,且同一时间只能绑定一个设备。
- 绘图操作通常应在
paintEvent或类似事件中执行。 - 资源管理:确保在堆上创建的 QPainter 对象及时调用
end()或通过析构函数释放。
QLinearGradient 概述
QLinearGradient 是 Qt 框架中的一个类,用于创建线性渐变效果。它通常与 QBrush 或 QPainter 结合使用,用于填充图形元素(如矩形、圆形等)的渐变颜色。线性渐变沿着一条直线从起点到终点平滑过渡颜色。
基本用法
QLinearGradient 的构造函数需要指定起点和终点坐标,渐变的颜色通过 setColorAt() 方法设置。以下是一个简单的示例
cpp
#include <QLinearGradient>
#include <QPainter>
// 创建线性渐变,从 (0, 0) 到 (100, 100)
QLinearGradient gradient(0, 0, 100, 100);
// 设置渐变颜色
gradient.setColorAt(0, Qt::red); // 起点为红色
gradient.setColorAt(0.5, Qt::green); // 中间点为绿色
gradient.setColorAt(1, Qt::blue); // 终点为蓝色
// 使用 QPainter 绘制渐变填充的矩形
QPainter painter(this);
painter.setBrush(QBrush(gradient));
painter.drawRect(0, 0, 100, 100);
关键方法
-
设置颜色点
setColorAt(qreal position, const QColor &color)position:范围 0.0 到 1.0,表示渐变路径上的相对位置。color:该位置的颜色值。
-
设置扩散模式
setSpread(QGradient::Spread spread)QGradient::PadSpread(默认):终点颜色填充剩余区域。QGradient::RepeatSpread:重复渐变。QGradient::ReflectSpread:反射渐变。
-
设置坐标模式
setCoordinateMode(QGradient::CoordinateMode mode)QGradient::LogicalMode(默认):坐标与绘制对象逻辑坐标一致。QGradient::ObjectMode:坐标相对于对象边界矩形。QGradient::StretchToDeviceMode:坐标相对于绘制设备。
示例:重复渐变
以下代码展示如何创建重复的线性渐变
cpp
QLinearGradient gradient(0, 0, 50, 50);
gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::cyan);
gradient.setSpread(QGradient::RepeatSpread); // 设置重复模式
QPainter painter(this);
painter.setBrush(QBrush(gradient));
painter.drawRect(0, 0, 200, 200); // 绘制一个较大的矩形以观察重复效果
注意事项
- 渐变坐标是相对于绘制对象的逻辑坐标。
- 颜色点的位置需按顺序设置(从 0.0 到 1.0)。
- 扩散模式和坐标模式可根据实际需求调整。
通过合理配置 QLinearGradient,可以实现丰富的视觉效果,适用于 UI 设计、数据可视化等场景。
3、提升导航组件
分别将其他三个导航控件提升为自定义控件,并设置标题属性





4、运行效果





原创不易,打字不易,截图不易,撸码不易,整理不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,灌水,请动动你的金手指,祝您早日实现财务自由。

