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、高级特点

  • 支持一对多、多对一、信号连接信号
  • 原生支持跨线程通信
  • 对象销毁时,信号槽连接自动断开
相关推荐
某不知名網友35 分钟前
ROS2进阶:服务通信、自定义SRV接口、参数服务器与基于服务的参数通信详解
java·开发语言·microsoft
java_nnnn1 小时前
LeetCode刷题滑动窗口(水果成篮+找到字符串中所有字母的异位词)Java
java·开发语言·leetcode
qetfw1 小时前
Bash 字符串处理:参数展开、序列与脚本执行方式
linux·开发语言·chrome·bash
小羊没烦恼!1 小时前
异步编程:线程概述及使用
java·开发语言·mysql·算法·c#
学Linux的语莫2 小时前
python中类的常见写法
开发语言·python·状态模式
需要8262 小时前
容器化 Java:镜像瘦身与 JVM 容器感知(cgroup)
java·开发语言·jvm
dyxal2 小时前
A2A 协议 v1.0 完全指南:方法名、Agent Card、三种绑定与 FastAPI 实战
开发语言·qt·fastapi
譕痕2 小时前
Rabbit 实例
java·开发语言·java-rabbitmq
综合简报2 小时前
黑五海外发稿投给谁?三类海外媒体发稿渠道的分工
开发语言·php·媒体
大风起兮云飞扬丶2 小时前
Java——线程池
java·开发语言