🌟 嗨,我是热爱嵌入式的涛涛同学!
每日一言
生活的选择权在你手中,想要什么样的人生,就去努力争取。
自定义按钮的信号与槽
那么我们自定义按钮的效果实现了,那么我们应该去实现信号与槽了,那么为什么我们的信号与槽怎么没有了呢?
因为我们继承的是QWidget这是因为 QWidget 本身不提供 clicked 信号,只有 QAbstractButton 及其子类(如 QPushButton)才内置了这个信号。当你继承 QWidget 时,需要手动实现信号的发射逻辑还有槽函数
一、为什么 QWidget 没有 clicked 信号?
QWidget 是所有控件的基类,它设计得非常 “基础”,只包含最通用的功能(如绘制、事件接收)。而 “点击” 是按钮特有的行为,因此:
- QWidget 没有 clicked 信号,也不会自动处理鼠标点击事件。
- QAbstractButton 作为按钮的抽象基类,才添加了 clicked 信号,并实现了点击逻辑。
我们在这个MyButton类这边将信号定义出来,在这个Widget将信号与槽进行绑定,那么为什么呢。因为我们的Mybutton这个控件是发信号的,我们这个Widget是捕获信号的,所以,而且我们这个需要使用ui->mybutton 这个只有Widget构造函数中才有的,创建了ui指针
那么这边我是直接用lambda表达式实现信号与槽的绑定
这个的话是因为我们自己写的信号的话,需要用到这个emit手动触发
但是我们想一下,那么官方的clicked信号是不是也是在内部实现呢??
解释:对于 Qt 内置的标准控件(如 QPushButton),不仅信号已经声明好,连信号的触发(emit 语句)也已经在控件内部实现了。这意味着当用户点击按钮时,Qt 框架会自动在适当的时机调用 emit clicked(),无需你手动编写这部分代码。
那么我们这个功能那么简单,为什么要去用信号与槽呢,不能用重写事件来写吗?
这些也是理解 Qt 事件与信号槽机制的关键困惑点:
事件处理与信号槽的功能重叠性:
你发现 “直接在重写的事件函数(如 mousePressEvent)中写逻辑” 和 “通过信号槽绑定执行逻辑” 都能实现相同效果(比如点击按钮打印文字),因此困惑:既然两者都能完成任务,它们的本质区别是什么?为什么需要两种方式?
自定义控件时的逻辑存放选择:
在设计自定义按钮时,你不确定逻辑应该直接写在事件处理函数里(如 mousePressEvent 中直接加载图片、打印日志),还是应该通过 “事件触发信号,信号连接外部槽函数” 的方式拆分存放。比如:
- 直接在 mousePressEvent 里写 qDebug(...) 可行;
- 让 mousePressEvent 发射 clicked() 信号,再在外部用槽函数写 qDebug(...) 也可行。
你想知道这两种方式的适用场景和设计原则。
“控件内部操作” 与 “通知外部” 的边界模糊:
你对 “哪些逻辑属于控件自己该做的(内部操作),哪些该通过信号告诉外部处理(通知外部)” 存在疑问。比如:
- 按钮点击后加载自身显示的图片,这是内部操作吗?
- 按钮点击后需要让窗口弹出提示,这应该由按钮自己处理,还是通过信号让窗口处理?
信号槽机制的必要性:
你可能在想:既然事件处理函数能直接完成所有操作,为什么还要额外定义信号、绑定信号槽(多写代码)?是不是有 “过度设计” 的嫌疑?尤其是在简单场景下,这种 “拆分” 的意义何在?
这些疑惑的核心,本质是对 Qt 中 “事件驱动” 与 “组件解耦” 设计思想的理解 —— 事件是控件感知用户操作的 “输入管道”,而信号槽是控件与外部组件 “协作通信” 的 “输出接口”。两种机制看似功能重叠,实则服务于不同的设计目标:前者解决 “控件如何感知操作”,后者解决 “操作发生后如何让其他组件协同响应”。
理清这些后,就能更清晰地判断:什么时候该直接在事件中处理(控件自身的独立逻辑),什么时候该用信号槽(需要外部组件参与的协同逻辑)。