当前位置: 首页 > news >正文

QT--事件系统

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、重写事件函数(如 keyPressEvent)
    • 1.什么是事件函数?
    • 2.如何使用?
      • 关键点
    • 3.适用场景
  • 二、重写 event 函数
    • 1.什么是event函数?
    • 2.如何使用?
      • 关键点
    • 3.适用场景
  • 三、使用事件过滤器(eventFilter)
    • 1.什么是事件过滤器(eventFilter)?
    • 2.如何使用?
      • 关键点
    • 3.适用场景
    • 4.为多个控件添加eventFilter
  • 总结


前言

今天来讲一个qt中非常重要的一个东西,事件系统
Qt 的事件系统是 Qt 应用程序处理用户交互(如按键、鼠标、滚轮等)的核心机制。事件是由系统或用户触发的某种“动作”(比如按下键盘移动鼠标),Qt 会将这些事件分发给相关的对象(通常是控件),这里介绍了三种处理事件的方法:

1.重写事件函数(如 keyPressEvent)
2.重写 event 函数
3.使用事件过滤器(eventFilter)

下面我详细总结每种方法的特点、用法和适用场景。


一、重写事件函数(如 keyPressEvent)

1.什么是事件函数?

直接在控件类中重写特定的事件处理函数,比如 keyPressEvent(按键事件)、mousePressEvent(鼠标点击事件)等。
这些函数是 Qt 定义好的虚函数,专门处理特定类型的事件。我们直接重写虚函数即可

2.如何使用?

定义一个自定义类(比如 MyEdit 继承 QLineEdit)
在这里插入图片描述
头文件中声明需要重写的事件函数(例如 void keyPressEvent(QKeyEvent *event))。
在源文件中实现这个函数,添加自定义逻辑。

//按键按下会触发这个事件函数keyPressEvent(属于事件系统)
void MyEdit::keyPressEvent(QKeyEvent *event)
{
    qDebug()<<"MyEdit key press event";
    QLineEdit::keyPressEvent(event);//调用基类的QLineEdit 让基类的keypressevent的作用也可以用
    event->ignore();/*在 MyEdit::keyPressEvent 中,你调用了 event->ignore(),
    表示“忽略这个事件并将其传递给父对象”(这里是 Widget)*/
}

我们在父类中也重写一个keyPressEvent

void Widget::keyPressEvent(QKeyEvent *)//让父窗口也响应
{
    qDebug()<<"Widget key press event";
}

此时运行这个程序所打印的顺序就是:
在这里插入图片描述
我们可以发现,当触发这个事件的时候,是先在子类响应,然后传递给父类

关键点

1.如果需要保留基类的默认行为(比如 QLineEdit 的输入功能),要调用基类的同名函数(QLineEdit::keyPressEvent)

2.默认情况下,事件在当前控件处理后就结束了,不会传递给父控件。

3. 如果想让父控件也处理事件,可以调用 event->ignore(),将事件“忽略”并传递给父控件

3.适用场景

当你只关心某个控件上的特定事件(比如按键、鼠标点击),并且处理逻辑简单时

二、重写 event 函数

1.什么是event函数?

event 是一个更底层的虚函数所有事件都会先经过它
然后才分发到具体的事件函数(如 keyPressEvent)
它就像一个“事件分发中心”,你可以在这里拦截所有事件

2.如何使用?

自定义类重写 event 函数
通过 QEvent::type() 判断事件类型,然后处理。
返回 true 表示事件已处理
返回 false 表示继续传递

1. 添加event函数

#ifndef MYEDIT_H
#define MYEDIT_H
#include<QLineEdit>
#include<QDebug>
class MyEdit:public QLineEdit//这个QLineEdit的父类是QWidget
{
    Q_OBJECT;//只有包含这个宏定义 这个类才能使用qt中的信号和槽
public:
    explicit MyEdit(QWidget * parent=nullptr);
protected:
    void keyPressEvent(QKeyEvent *event);
    bool event(QEvent *event);//这里添加event函数 
};

#endif // MYEDIT_H

2.实现event函数

bool MyEdit::event(QEvent *event)
{
    if(event->type()==QEvent::KeyPress)//判断类型
    {
        qDebug()<<tr("my edit event")<<Qt::endl;
        //return false ;
    }
    return QLineEdit::event(event);
}

提问!!!!!!
如果在if中返回true会打印什么?
如果在if中返回true会打印什么?
如果if中不return 会打印什么?

大家仔细思考一下

1. 如果返回true,那就拦截了这个事件,不会继续传递给父类了,所以只会打印my edit event
2. 如果返回false,没有拦截这个事件,继续往父类传递,会打印my edit event,Widget key press event
那这里如果仔细思考的话,可能会问,为什么没有打印MyEdit key press event,怎么没有进入这个自定类重写的keyPressEvent呢?
答案: return false 的作用:
返回 false 表示“当前类放弃处理这个事件”,直接交给基类的 event 函数。基类的 event 会调用基类的 keyPressEvent,而不会考虑子类的重写
3.不写return的话 会打印三句话 顺序为my edit event, MyEdit key press event, Widget key press event

关键点

调用顺序event 先于 keyPressEvent 执行
如果在 event 中 返回 true,事件就不会到达 keyPressEvent。
通常需要调用基类的 event 函数,确保默认分发逻辑正常工作。

3.适用场景

当你需要处理多种事件类型,或者想在事件分发之前做一些统一处理时

三、使用事件过滤器(eventFilter)

1.什么是事件过滤器(eventFilter)?

事件过滤器是一个特殊的机制,允许一个对象(通常是父对象)在事件到达目标对象之前拦截和处理它。
它定义在 QObject 中,通过 installEventFilter 安装

2.如何使用?

父类(如 Widget)重写 eventFilter 函数
判断事件的目标对象(QObject *object)和事件类型(QEvent *event)。
返回 true 表示事件已处理,停止传递;返回 false 表示继续传递。
目标对象上安装过滤器installEventFilter

line_edit->installEventFilter(this);//为这个安装一个父节点的事件过滤器
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == line_edit){
        if(event->type() == QEvent::KeyPress){
            qDebug() << "widget eventfilter catch line_edit" ;
            return false;
        }
    }
    return QWidget::eventFilter(watched, event);//返回基类的事件过滤器
}

注意打印顺序
在这里插入图片描述

关键点

调用顺序:eventFilter 是事件传递的第一个环节,在 event 和 keyPressEvent 之前。
需要手动安装过滤器,否则不起作用。
可以为多个子控件安装同一个过滤器,灵活性很高。

3.适用场景

当你需要从父窗口统一监控处理多个子控件的事件时。
比如拦截特定控件的特定事件(如滚轮、按键),或者实现全局事件处理。

4.为多个控件添加eventFilter

我们弄一个滚轮事件

if(watched==ui->textEdit)
    {
        //捕获滚轮事件
        if(event->type()==QEvent::Wheel)
        {
            QWheelEvent * wheelevent=static_cast<QWheelEvent*>(event);//转换形式
            if(wheelevent->angleDelta().y()>0)//y是垂直方向 x是水平方向
            {
                qDebug()<<"catch wheel event angleDelta().y()>0 ";
                ui->textEdit->zoomIn();//放大文本
            }
            else
            {
                qDebug()<<"catch wheel event angleDelta().y()<0 ";
                ui->textEdit->zoomOut();//缩小文本
            }
            return true;//不继续让父类继续处理
        }
        return false;//如果不是滚动事件 那就交给父节点处理
    }

在这里插入图片描述
实现滚轮往上滚 字体变大的效果

总结

Qt 事件系统的本质
Qt 的事件系统是处理用户交互(如按键、鼠标、滚轮)的核心机制。
事件从系统产生后,按照特定顺序分发给控件,开发者可以通过不同方式拦截和处理这些事件。
在这里插入图片描述
什么时候用 event 还是 eventFilter?
用 event 当你只关心当前控件所有事件
用 eventFilter 当你想从父控件监控子控件

相关文章:

  • 智能合约安全指南 [特殊字符]️
  • 【音视频】封装格式与音视频同步
  • 六、Redis 高级功能详解:BitMap、HyperLogLog、Geo、Stream
  • 《用Python+PyGame开发双人生存游戏!源码解析+完整开发思路分享》
  • 【第13节】C++设计模式(行为模式)-Template(模板)模式
  • 【leetcode100】全排列
  • 【落羽的落羽 C++】C++入门基础:输入与输出,缺省参数,函数重载
  • FastGPT 源码:RRF、Rerank 相关代码
  • FastGPT 引申:基于 Python 版本实现 Java 版本 RRF
  • 源码编译安装httpd
  • 示例:在WPF中如何使用Segoe MDL2 Assets图标和使用该图标的好处
  • 算力100问☞第72问:算力与算法、数据的关系是什么?
  • JavaScript 变量命名规范
  • 自编码器——数据降维及特征提取
  • slf4j和log4j的区别与使用
  • Mysql从入门到精通day2————数据表操作
  • 第五十三:v-model修饰符
  • 深度学习之图像学习知识点
  • DeepSeek未来发展趋势:开创智能时代的新风口
  • 高频 SQL 50 题(基础版)_610. 判断三角形
  • 搭建网站团队计划/百度快速排名优化技术
  • 网站模板下载模板下载/今天的最新消息新闻
  • 柳州 网站推广/太原免费网站建站模板
  • 重庆seo网站设计/厦门seo外包
  • 淮北建设工程质量安全站网站/房地产营销策略有哪些
  • 网站建设与微信公众号绑定/国际军事形势最新消息