一、信号(Signal)
- 概念:信号是控件/对象在特定事件触发时发出的通知
- 特点:只声明、不实现、无返回值、可以带参数
- 示例:按钮被点击、输入框内容改变、窗口关闭、定时器超时
二、槽(slot)
- **概念:**是用来响应信号的普通成员函数
- **特点:**需要自己实现、可以有返回值、可带参数、能被普通函数直接调用
- **作用:**接收信号,执行业务逻辑(点击按钮后执行操作)
三、连接(connect)
- 概念: 把信号发送者的信号 和接收者的槽函数绑定,信号触发时自动执行槽函数。
- 函数本体:
cpp
// 静态成员函数,QObject 内部定义
static QMetaObject::Connection connect(
const QObject *sender, // 1. 信号发送者对象
const QMetaMethod &signal, // 2. 要发射的信号
const QObject *receiver, // 3. 槽函数接收者对象
const QMetaMethod &slot, // 4. 响应的槽函数
Qt::ConnectionType type = Qt::AutoConnection
);
- 示例:
cpp
connect(发送者, &类名::信号, 接收者, &类名::槽, 连接方式);
- 四个核心参数:
- **sender:**信号发送者(谁要发射信号)
- **signal:**信号函数(触发什么事件会发射信号)
- **receiver:**信号接收者(谁来处理这个信号)
- **slot:**槽函数(触发和自动执行的槽函数)
- **第五个可选参数:**连接类型
- **Qt::AutoConnection :**默认,自动判断是否跨线程
- **Qt::DirectConnection :**同步直接调用
- **Qt::QueuedConnection :**跨线程异步队列调用
四、信号和槽的使用
1、通过 Qt Creator ⽣成信号槽代码
- 创建好一个项目

- 点击widget.ui

- 将Push Button按钮拖至窗口

- 右击Push Button点击转到槽,点击clecked

- 写槽函数并运行


- 点击窗口的按钮,发送信号,就会执行关闭窗口的槽函数

2、自定义信号和槽
前提:
- 类必须继承 QObject
- 类内必须写 Q_OBJECT 宏
- 自定义信号写在 signals: 下,只声明,不实现
自定义信号:
- 返回值为void
- 只声明不定义
- 必须写到"signals" 下
- 可以含参数,也可以重载
- 只能用emit触发
自定义槽:
- 返回值为void
- 需要声明和定义
- 早期需要写到"public slots" 下,现在可以直接写到"public"作用域或全局中
示例:
运行之后发射信号自动执行myslot函数,打出日志我的槽函数
3、信号和槽的断开
disconnect:
cpp
disconnect(发送者, 信号, 接收者, 槽函数);
断开指定的一条连接:
cpp
// 绑定
connect(sender, &A::sig, receiver, &B::slot);
// 精准断开这条
disconnect(sender, &A::sig, receiver, &B::slot);
断开某个发射对象:
cpp
// 断开 sender 所有信号的全部连接
disconnect(sender, nullptr, nullptr, nullptr);
断开某个接收对象:
cpp
// 断开 receiver 所有槽监听
disconnect(nullptr, nullptr, receiver, nullptr);
断开某个特定的信号:
cpp
// 该信号绑定的所有槽,全部失效
disconnect(sender, &A::sig, nullptr, nullptr);
4、使用Lambda 表达式定义槽函数
基本语法:
cpp
connect(发送者, 信号, 接收者, [捕获列表](参数){
// 槽函数逻辑
});
捕获方式:
示例:
cpp
connect(ui->pushButton, &QPushButton::clicked,
this, [=]()
{
ui->label->setText("Lambda 槽执行了");
qDebug() << "按钮被点击";
});
5、带参数的信号和槽
核心规则:
- 信号可以带参数,槽参数数量 ≤ 信号参数数量
- 参数类型必须匹配
- 槽可以少接收参数,不能多接收
示例:
cpp
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
// 自定义带参信号:只声明,不实现
signals:
void msgSig(QString content);
void numSig(int a, int b);
// 自定义带参槽
private slots:
void msgSlot(QString s);
void numSlot(int x,int y);
};
五、总结
1、核心作用
- Qt 对象间解耦通信机制,替代回调函数,用于事件传递、数据交互。
2、三大核心
信号signal:
- 事件触发时主动发出的通知
- 无返回值、只声明不实现、可带参数
- 自定义信号用 emit 信号(参数) 手动发射
槽slot:
- 用来接收并处理信号的函数
- 可以是普通成员函数、slots 函数、Lambda表达式
连接connect:
- 绑定:发送者 → 信号 与 接收者 → 槽
- 格式: connect(发送者,信号,接收者,槽)
3、使用硬性条件
- 类必须继承 QObject
- 类开头必须加 Q_OBJECT 宏(moc 元对象机制)
4、参数匹配规则
- 槽参数数量 ≤ 信号参数数量
- 参数类型必须一致
- 信号多的参数会自动舍弃
5、断开连接disconnect
- **普通槽:**和 connect 参数一一对应断开
- **Lambda槽:**必须保存 QMetaObject::Connection 句柄断开
- 填 nullptr可批量断开全部连接
6、高级特点
- 支持一对多、多对一、信号连接信号
- 原生支持跨线程通信
- 对象销毁时,信号槽连接自动断开


