一. Qt 的事件分发 event
1. 核心知识点:
event(QEvent *e) 是 Qt 事件系统的总入口函数,所有事件(鼠标、键盘、绘制等)都会先进入这个函数,再分发到具体的事件处理函数(如 mousePressEvent)
2. 核心作用:
统一拦截 / 处理多种类型事件
处理没有专属虚函数的事件(如自定义事件)
决定事件是否继续传递给父对象
3. 过程的理解
知识点是 Qt 交互的 "底层逻辑",核心是理解事件怎么从 "发生" 到 "被处理":
event () 当作事件的 "总接待处",专门处理事件的
事件分发返回真:当前事件处理完成
返回假:未处理,自动触发自动上传机制告诉副控件

event()函数进行事件分发,根据具体事件情况进行强类型转换,转换成对应指针,
// 在调用受保护的虚函数(这些虚函数叫做受保护的事件函数)
// 意思就是类型转换成对应子事件的类型,在调用该事件函数

4.应用
处理底层输入事件(鼠标 / 键盘 / 触摸)
Qt 没有将「鼠标移动、键盘按键、鼠标滚轮」等事件封装为通用信号(因为这类事件高度定制),需要重写对应的事件函数

需要手写的(举例)
捕获鼠标移动 / 点击 / 释放的精确坐标;
监听特定键盘按键(比如按 ESC 关闭窗口、按方向键控制界面元素);
处理触摸屏幕的多点触控事件;
拦截窗口关闭事件(比如关闭前弹出确认框)
二.事件和信号关系

任务分发时,默认先实现设置的内容,在完成对应分发内容

1. 机制
子类提示处理不了,交给父类处理
事件是核心机制,把操作系统能力封装起来,主要是异步操作,实现程序员和操作系统的衔接
信号是为了实现对象间的耦合性(不关心做什么,只关心要不要发出来这个信号 )
2. 信号事件区别
信号面向的是群体主键,事件面向的是核心机制(先有事件,再根据情况分发信号)
三.事件过滤
1.事件过滤和事件分发
是事件分发函数之前提供的一个机制
事件分发是直接作用到哪个对象,事件过滤是全局过滤
2. 举例
void QObject::installEventFilter(QObject *filterObj)
事件过滤器:eventFilter()
2.1 规则
return true :事件被吃掉,目标对象收不到
return false / 交给父类:事件继续传递
2.2 核心作用
让 filterObj 成为当前对象的「事件监听器」,当前对象的所有事件都会先经过 filterObj 的 eventFilter 函数
参数 filterObj 事件过滤器对象(必须是 QObject 子类,且重写了 eventFilter 函数)
所属类 QObject(Qt 所有对象的基类,包括所有控件:QLabel、QWidget、QPushButton 等)
2.3 筛选的作用
相当于给 InnerLabel(当前对象)装了一个 "监控摄像头"(filterObj 即 Widget),InnerLabel 的所有 "动作"(事件)都会先被摄像头拍到,摄像头可以选择 "放行"(事件继续传递)或 "拦截"(事件终止)
3. 使用场景与注意事项
(1)适用场景
监听第三方控件事件:无法修改控件源码(比如 Qt 原生 QLabel),但需要监听其事件;
统一管控多个控件:一个过滤器监听多个控件(比如同时监听 Label、Button、LineEdit);
临时拦截事件:比如 "权限不足时禁止点击按钮 / Label";
调试事件:快速打印某个控件的所有事件,定位问题。
(2)注意事项
必须重写 eventFilter:只安装过滤器但不重写 eventFilter,相当于没装(事件直接放行);
不要漏写父类返回:最后必须 return QWidget::eventFilter(...),否则会影响其他控件的事件;
避免循环过滤:不要在 eventFilter 里给当前 watched 对象再次安装过滤器,会导致死循环;
记得移除过滤器:如果过滤器对象(Widget)先于目标对象(InnerLabel)销毁,需提前移除,否则可能崩溃
过滤安装到父对象上
4. 过滤器函数(必须和安装过滤器搭配用)
4.1过滤器函数
bool eventFilter(QObject *watched, QEvent *event) override{}
// watched:触发事件的对象(比如 in_label)
// event:具体的事件(鼠标点击、键盘输入、绘制等)
使用: watched == ui->pushButton
只处理这个按钮的事件,避免干扰别的控件
4.2 在构造函数中给主控件安装过滤器
// 让 this(当前窗口)去监听 ui->pushButton
ui->pushButton->installEventFilter(this);
installEventFilter(用于给函数安装过滤) → 给住户装监控的动作(告诉安保:"我要监控这个住户的所有进出");
eventFilter → 安保的监控规则 / 处理逻辑(安保看到住户进出时,判断 "放行 / 拦截 / 记录")
5.流程图

