当前位置: 首页 > article >正文

QT从入门到精通(二) ——信号与槽机制

Qt 的信号与槽机制(Signal and Slot)是 Qt 框架 中用于对象间通信的核心机制之一。它允许对象之间进行松耦合的事件驱动式通信,尤其适合 GUI 应用程序 中的事件处理。


1. 基本概念

信号 (Signal)

  • 当对象的状态发生变化时,它会发出一个信号
  • 信号是一种声明,不需要实现。
  • 信号不需要知道谁会接收它,也就是松耦合的设计。

槽 (Slot)

  • 槽是一个普通的函数,可以用来接收信号。
  • 当信号发出时,与之关联的槽函数将被自动调用。
  • 槽可以是成员函数、普通函数或 lambda 表达式。

连接 (Connect)

  • 信号和槽通过 QObject::connect() 进行连接。
  • 当信号发出时,Qt 会自动调用与其连接的槽。

2. 信号与槽的工作原理

Qt 的信号与槽机制基于 元对象系统(Meta-Object System),它使用以下特性:

  • Q_OBJECT 宏:类中必须包含此宏,表示该类支持信号与槽。
  • moc 工具:Qt 的元对象编译器,会处理信号与槽相关的代码。

Qt 的 事件循环 负责在对象间传递信号,确保槽在正确的上下文中执行。


3. 信号与槽的定义与使用

1) 定义一个信号与槽

要使用信号与槽,必须满足以下条件:

  • 类需要继承自 QObject
  • 在类声明中加入 Q_OBJECT 宏。
  • 使用 signals 关键字声明信号。
  • 使用 slots 关键字声明槽函数。

示例代码:

定义类:
#include <QObject>
#include <QDebug>

class MyObject : public QObject {
    Q_OBJECT

public:
    explicit MyObject(QObject *parent = nullptr) : QObject(parent) {}

signals:
    void mySignal(int value); // 声明一个信号

public slots:
    void mySlot(int value) {  // 定义一个槽
        qDebug() << "Received signal with value:" << value;
    }
};

在这里插入图片描述

连接信号与槽:
#include <QCoreApplication>

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    MyObject obj1, obj2;

    // 连接信号与槽
    QObject::connect(&obj1, &MyObject::mySignal, &obj2, &MyObject::mySlot);

    // 触发信号
    emit obj1.mySignal(42);

    return a.exec();
}

在这里插入图片描述

输出结果:

Received signal with value: 42

2) 连接方式

QObject::connect 有多种形式,支持不同的连接模式。

语法:

QObject::connect(sender, SIGNAL(signalName(params)), receiver, SLOT(slotName(params)));

现代写法(推荐): 使用函数指针和 lambda 表达式。

QObject::connect(sender, &ClassName::signalName, receiver, &ClassName::slotName);

Lambda 表达式示例:

QObject::connect(&obj1, &MyObject::mySignal, [](int value) {
    qDebug() << "Lambda slot received value:" << value;
});

3) 信号与槽的重载

如果信号或槽有多个重载版本,必须在连接时指定函数指针。

示例:

class Example : public QObject {
    Q_OBJECT
signals:
    void valueChanged(int);
    void valueChanged(double);
};

Example obj;
QObject::connect(&obj, static_cast<void (Example::*)(int)>(&Example::valueChanged), 
                 &obj, [](int value) { qDebug() << "Int version called:" << value; });

4. 信号与槽的特点

  1. 松耦合
    • 信号的发送者和槽的接收者无需了解彼此的存在。
  2. 类型安全
    • 信号与槽的参数必须匹配,否则编译器会报错。
  3. 多对多关系
    • 一个信号可以连接多个槽。
    • 多个信号可以连接到同一个槽。
  4. 线程安全
    • 跨线程连接时,信号会安全地传递到接收线程。

5. 信号与槽的连接类型

在多线程程序中,Qt 提供了不同的连接类型:

连接类型:

  1. Qt::AutoConnection(默认)

    • 如果信号和槽在同一线程中,则为直接连接
    • 如果在不同线程中,则为队列连接
  2. Qt::DirectConnection

    • 信号发出后,槽会立即执行,位于发送线程。
  3. Qt::QueuedConnection

    • 信号会进入接收线程的事件队列,由接收线程执行。
  4. Qt::BlockingQueuedConnection

    • 发送线程阻塞,直到槽函数执行完毕。仅适用于跨线程。

6. 注意事项

  1. 使用 Q_OBJECT
    • 类必须继承自 QObject,并包含 Q_OBJECT 宏,否则信号与槽不会工作。

在这里插入图片描述

  1. moc 工具的支持

    • 需要使用 Qt 的 Meta-Object Compiler (moc) 进行预处理,否则信号与槽无法解析。
  2. 参数匹配

    • 信号与槽的参数个数和类型必须兼容。信号的参数可以多于槽的参数,但前者必须兼容后者。
  3. 析构时自动断开连接

    • 当对象被销毁时,Qt 会自动断开与该对象相关的所有连接。

在这里插入图片描述

总结

Qt 的信号与槽机制是一种强大且灵活的事件处理机制,它提供了类型安全松耦合的通信方式,广泛用于 Qt 应用程序中的 组件间交互事件处理
现代 C++ 写法(函数指针和 Lambda 表达式)更加简洁和安全,推荐在新代码中使用。


http://www.kler.cn/a/446019.html

相关文章:

  • IntoTheBlock 联创:Web3 基础设施正在被过度建设,我们正在盲目行事
  • 【Mongo工具】Mongo迁移工具之Mongo-shake
  • windows C#-使用构造函数
  • ArkUI性能优化(0)—DevEco Profiler调优工具
  • 力扣275.H制数II (二分法 求最大)
  • 二八(vue2-04)、scoped、data函数、父子通信、props校验、非父子通信(EventBus、provideinject)、v-model进阶
  • Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
  • 使用ZLMediaKit 开源项目搭建RTSP 服务器
  • Python爬虫实战:深入Lazada商品详情获取
  • 前端导出PDF的组件及方法
  • C#方法参数修饰符ref/out/in/params
  • 智能体实战(需求分析助手)一、需求概述及迭代规划
  • Docker安装与架构
  • 28、论文阅读:基于像素分布重映射和多先验Retinex变分模型的水下图像增强
  • Facebook的去中心化探索:社交平台的新型发展趋势
  • GIT命令使用手册(详细实用版)
  • wxpyton+wxFormBuilder加法运算示例
  • docker 存储管理
  • 【LeetCode每日一题】——434.字符串中的单词数
  • Python的3D可视化库【vedo】2-5 (plotter模块) 坐标转换、场景导出、添加控件