码上通QT实战06--导航按钮事件

1、前言

在Qt中实现导航按钮事件通常涉及信号与槽机制、事件处理或QAction的触发。以下是几种常见实现方式:

  1. 使用QPushButton的clicked信号
  2. 通过QAction实现快捷键导航
  3. 重写事件过滤器处理特定按键
  4. 在QML中实现导航按钮
  5. 使用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::LeftButtonQt::RightButton)。
  • event->pos()
    返回鼠标相对于当前控件的坐标(QPoint 类型)。
  • event->globalPos()
    返回鼠标在屏幕全局坐标系中的坐标。

注意事项

  • 若需处理其他鼠标事件(如释放或移动),需同时重写 mouseReleaseEventmouseMoveEvent
  • 在 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 的参数 eventQEvent 类型,包含事件的基本信息(如时间戳)。
  • 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),可以在重写函数中显式调用,但通常这不是必须的。
  • leaveEvententerEvent 是成对的,分别处理鼠标进入和离开控件的事件。

完整代码

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);

关键方法

  1. 设置颜色点
    setColorAt(qreal position, const QColor &color)

    • position:范围 0.0 到 1.0,表示渐变路径上的相对位置。
    • color:该位置的颜色值。
  2. 设置扩散模式
    setSpread(QGradient::Spread spread)

    • QGradient::PadSpread(默认):终点颜色填充剩余区域。
    • QGradient::RepeatSpread:重复渐变。
    • QGradient::ReflectSpread:反射渐变。
  3. 设置坐标模式
    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、运行效果

复制代码
原创不易,打字不易,截图不易,撸码不易,整理不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,灌水,请动动你的金手指,祝您早日实现财务自由。
相关推荐
hqwest1 天前
码上通QT实战07--主窗体消息栏设计
开发语言·qt·qt事件·主窗体·stackedwidget
shughui1 天前
实现Python多版本共存
开发语言·python·pip
dhdjjsjs1 天前
Day58 PythonStudy
开发语言·python·机器学习
你真的可爱呀1 天前
自定义颜色选择功能
开发语言·前端·javascript
mzhan0171 天前
perl: redhat9, perl-interpreter.rpm 一个包分成很多个小包
开发语言·perl·redhat·rpm
福楠1 天前
C++ STL | list
c语言·开发语言·数据结构·c++·算法·list
奔跑的web.1 天前
TypeScript类型系统核心速通:从基础到常用复合类型包装类
开发语言·前端·javascript·typescript·vue
小白学大数据1 天前
百科词条结构化抓取:Java 正则表达式与 XPath 解析对比
java·开发语言·爬虫·正则表达式
ss2731 天前
volatile的可见性、安全发布的秘密与ThreadLocal原理
java·开发语言