Qt—信号和槽

一、信号(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(发送者, &类名::信号, 接收者, &类名::槽, 连接方式);
  • 四个核心参数:
  1. **sender:**信号发送者(谁要发射信号)
  2. **signal:**信号函数(触发什么事件会发射信号)
  3. **receiver:**信号接收者(谁来处理这个信号)
  4. **slot:**槽函数(触发和自动执行的槽函数)
  • **第五个可选参数:**连接类型
  1. **Qt::AutoConnection :**默认,自动判断是否跨线程
  2. **Qt::DirectConnection :**同步直接调用
  3. **Qt::QueuedConnection :**跨线程异步队列调用

四、信号和槽的使用

1、通过 Qt Creator ⽣成信号槽代码

  • 创建好一个项目
  • 点击widget.ui
  • 将Push Button按钮拖至窗口
  • 右击Push Button点击转到槽,点击clecked
  • 写槽函数并运行
  • 点击窗口的按钮,发送信号,就会执行关闭窗口的槽函数

2、自定义信号和槽

前提:

  1. 类必须继承 QObject
  2. 类内必须写 Q_OBJECT 宏
  3. 自定义信号写在 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、高级特点

  • 支持一对多、多对一、信号连接信号
  • 原生支持跨线程通信
  • 对象销毁时,信号槽连接自动断开
相关推荐
用户8055336980320 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner20 小时前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript