Qt笔记:信号与槽+事件系统
信号与槽
1 信号与槽
定义
信号:控件状态变化时主动发射的通知(按钮点击、文本修改),无返回值,仅负责广播消息。 槽函数:普通成员函数,用来接收信号、执行业务逻辑,可被直接调用。connect完成信号发射端、槽接收端绑定,实现通信。
核心优势
完全解耦:发送方不用关心谁接收、接收方不用关心信号来源,降低类耦合,UI 逻辑分离,便于维护、复用控件。
2 五种信号槽连接方式
函数指针(类成员函数)connect(btn,&QPushButton::clicked,this,&Widget::onClick),类型编译期校验,最稳妥。
Lambda 表达式适合临时简短逻辑,无需单独写槽函数。
槽函数字符串形式(旧版 SIGNAL/SLOT 宏,Qt6 不推荐)运行时校验,写错无编译报错,容易出错。
静态重载函数 connect适配重载信号手动指定参数类型。
Qt5 风格自动连接(on_控件名_信号名)命名规范自动绑定,无需手写 connect。
3 Lambda 实战:登录校验
按钮点击信号绑定 Lambda,直接获取账号、密码输入框文本,做非空、账号密码比对判断,弹窗提示登录成功 / 失败,不用额外定义槽函数,精简界面交互代码。
4 自定义信号
在类头文件signals:区块声明自定义信号,无需实现函数体,业务处用emit 自定义信号(参数)触发。通过 connect 绑定自定义信号到槽函数,实现组件间自定义消息传递,多用于子控件向父窗体传参。
5 disconnect + sender
disconnect():解绑信号槽,分为断开指定连接、断开对象所有信号、断开对象所有槽三种用法,用于临时禁用按钮事件、动态切换逻辑。
QObject *sender():槽函数内调用,获取触发当前槽的信号发送对象,强转对应控件类型,实现多个控件复用同一个槽函数。
Qt 事件系统
1 事件 VS 信号槽
事件
底层原生消息(鼠标、键盘、绘制、窗口缩放),由 QEvent 封装,Qt 事件循环依次派发,是底层基础。
核心区别
- 事件:底层原生消息,可拦截、过滤、重写,信号槽是上层封装
- 信号槽由事件触发生成(按钮点击事件→发射 clicked 信号)
- 事件偏向底层交互拦截,信号槽偏向上层业务逻辑解耦
2 常见事件重写
继承控件重写对应事件虚函数实现自定义行为:
mousePressEvent鼠标按下、mouseMoveEvent鼠标移动、mouseReleaseEvent鼠标抬起keyPressEvent键盘按键paintEvent界面绘制closeEvent窗口关闭拦截; 可调用event->accept()消费事件、ignore()继续向上传递事件
3 事件过滤器
原理:给目标控件安装installEventFilter(this),重写eventFilter函数,在事件抵达控件前提前拦截处理。
优势:不用继承控件重写事件,一个过滤器可以管控多个控件事件,统一拦截鼠标、键盘事件,适合全局按键屏蔽、统一样式 hover 处理。
核心总结
信号槽:上层业务解耦通信,日常界面交互首选;自定义信号实现组件通信,Lambda 简化短逻辑,sender 复用槽、disconnect 动态解绑。
事件系统:底层消息驱动,重写事件做控件定制,事件过滤器实现全局事件拦截,信号槽本质是 Qt 对原生事件的上层封装。
