qt 信号和槽

发布于:2025-07-04 ⋅ 阅读:(10) ⋅ 点赞:(0)
  1. 理解基本概念
    信号(Signals):是特殊的函数,当对象的状态发生变化时会发出信号。信号无需实现体,只需在类中声明。例如,当用户点击一个按钮时,按钮对象会发出 clicked() 信号。
    槽(Slots):是普通的 C++ 成员函数,可以被连接到信号上。当信号被发出时,与之连接的槽函数会被自动调用。槽函数可以有参数和返回值,也可以是虚函数。
    连接(Connection):使用 QObject::connect() 函数将信号和槽连接起来。连接指定了哪个对象的哪个信号连接到哪个对象的哪个槽。

语法
connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot);
连接重载函数
qOverload<Args…>(&Class::function)

  1. 深入学习连接类型
    QObject::connect() 函数有不同的连接类型,如 Qt::DirectConnection(直接连接,信号发出时立即调用槽函数)、Qt::QueuedConnection(队列连接,信号发出后,槽函数在接收者所在线程的事件循环中被调用)、Qt::BlockingQueuedConnection(阻塞队列连接,类似队列连接,但会阻塞发送者线程直到槽函数执行完毕)等。了解不同连接类型的使用场景和区别。
    1. Qt::AutoConnection
    描述:这是 connect 函数的默认连接方式。当使用此连接方式时,Qt 会根据发送者和接收者所在的线程自动选择合适的连接方式。
    工作机制:
    如果发送者和接收者在同一线程,会使用 Qt::DirectConnection 方式。
    如果发送者和接收者不在同一线程,会使用 Qt::QueuedConnection 方式。

  2. 理解元对象系统的基本概念
    元对象系统的组成:Qt 元对象系统主要由三个部分组成:QObject 类、Q_OBJECT 宏和 moc(元对象编译器)。QObject 是所有使用元对象系统的 Qt 类的基类,Q_OBJECT 宏用于在类中启用元对象系统,moc 则负责处理 Q_OBJECT 宏并生成必要的代码。
    信号与槽机制:信号与槽是 Qt 元对象系统最常用的功能之一,它提供了一种对象间通信的机制。当一个对象的状态发生变化时,它可以发出一个信号,其他对象可以连接这个信号到一个槽函数,当信号发出时,槽函数会被调用。
    运行时类型信息:Qt 元对象系统提供了运行时类型信息(RTTI)的功能,你可以使用 qobject_cast 函数在运行时进行安全的类型转换。
    动态属性系统:Qt 允许你在运行时为对象添加、查询和删除属性,这为对象的动态配置提供了很大的灵活性。

先后顺序:通常先使用 Q_DECLARE_METATYPE 进行编译时的声明,让 QVariant 能够识别自定义类型;然后如果需要在信号和槽、多线程等场景中使用该自定义类型,就使用 qRegisterMetaType 进行运行时的注册。

不同线程间必须使用 Q_DECLARE_METATYPE 和 qRegisterMetaType 的原因

  1. 线程间信号传递机制
    不同线程间的信号传递采用的是 Qt::QueuedConnection(队列连接)。在这种连接方式下,当信号发出时,信号和其携带的参数会被封装成一个事件,放入接收线程的事件队列中。接收线程在处理事件时,会从事件中提取参数并调用相应的槽函数。
  2. 元对象系统的作用
    为了能正确地封装和提取事件中的参数,Qt 的元对象系统需要知道参数的类型信息。qRegisterMetaType 函数的作用就是在运行时将自定义类型注册到元对象系统中,让元对象系统能够识别该类型。而 Q_DECLARE_METATYPE 宏则是为自定义类型生成必要的元信息,这些元信息对于元对象系统在事件处理过程中进行类型检查、复制和转换等操作是必不可少的。
  3. 缺少 Q_DECLARE_METATYPE 导致的问题
    如果不使用 Q_DECLARE_METATYPE,元对象系统就无法获取自定义类型的完整元信息。在将参数封装到事件中或者从事件中提取参数时,就会因为缺少必要的类型信息而无法正确处理,可能会导致程序崩溃、参数丢失或者出现未定义行为。

什么是元对象
元对象是一种描述对象信息的数据结构,它包含了对象的类名、属性、方法、信号、槽等信息。在 Qt 里,每个继承自 QObject 类并使用了 Q_OBJECT 宏的类都会生成一个对应的元对象。这个元对象由元对象编译器(moc,Meta-Object Compiler)在编译时生成,它存储了类的元数据,使得程序在运行时能够动态地获取和操作这些信息。
元对象包含的主要信息
类名:表示该对象所属的类的名称。
属性列表:记录了类中定义的所有属性,包括属性的名称、类型和访问方法。
方法列表:包含了类的所有成员函数,包括普通方法、信号和槽。
信号和槽信息:记录了类中定义的信号和槽的名称、参数类型等。