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

  • 支持一对多、多对一、信号连接信号
  • 原生支持跨线程通信
  • 对象销毁时,信号槽连接自动断开
相关推荐
geovindu2 小时前
go:Decorator Pattern
开发语言·设计模式·golang·装饰器模式
故事和你913 小时前
洛谷-算法2-1-前缀和、差分与离散化1
开发语言·数据结构·c++·算法·深度优先·动态规划·图论
励志的小陈9 小时前
贪吃蛇(C语言实现,API)
c语言·开发语言
Makoto_Kimur9 小时前
java开发面试-AI Coding速成
java·开发语言
laowangpython9 小时前
Gurobi求解器Matlab安装配置教程
开发语言·其他·matlab
wengqidaifeng9 小时前
python启航:1.基础语法知识
开发语言·python
观北海9 小时前
Windows 平台 Python 极简 ORB-SLAM3 Demo,从零实现实时视觉定位
开发语言·python·动态规划
小短腿的代码世界10 小时前
Qt Concurrent 深度解析:并发编程范式与源码级实现原理
qt·系统架构·lucene
Ulyanov11 小时前
《PySide6 GUI开发指南:QML核心与实践》 第二篇:QML语法精要——构建声明式UI的基础
java·开发语言·javascript·python·ui·gui·雷达电子对抗系统仿真