一、信号与槽机制概述
四、信号与槽的连接
六、自定义信号与槽
思考
定义与作用 :信号与槽是Qt中的核心通信机制,用于实现对象间的数据交互和事件处理。当特定事件发生时,对象会发出信号,而与之相连的槽函数会被自动调用。
特点 :信号和槽是松耦合的,它们之间不需要直接的引用。Qt的元对象系统(Meta-Object System)提供了这种通信机制。
二、信号与槽的定义
信号(Signal) :是在特定情况下被发射的事件。信号函数只能声明,不能定义,使用
signals
关键字进行声明,不能有返回值,只能为void
类型。信号可以使用emit
关键字来发射。例如:class MyClass : public QObject { Q_OBJECT signals: void mySignal(); void mySignalWithParam(int data); };
槽(Slot) :槽函数是响应特定信号而调用的函数。槽函数是普通的 C++ 成员函数,可以像其他函数一样被调用,并且它们可以有参数和返回值。槽函数的声明和普通成员函数一样,但在 Qt 的元对象系统中需要使用
slots
进行标记,以便与信号进行连接。例如:class MyClass : public QObject { Q_OBJECT public slots: void mySlot(); void mySlotWithParam(int data); };
三、信号的发送与槽的调用
信号的发送 :信号是由对象发出的,当其内部状态发生变化时,对象的客户端或所有者可能会感兴趣。信号是公共访问函数,可以从任何地方发出,但我们建议只从定义信号及其子类的类发出它们。当信号被发出时,与之连接的槽函数通常会立即执行,就像普通函数调用一样。如果几个槽连接到一个信号,当信号发出时,这些槽将按照它们连接的顺序一个接一个地执行。
槽的调用 :当与槽连接的信号发出时,它被调用。槽是正常的 C++ 函数,可以正常调用;它们唯一的特点是信号可以连接到它们。由于槽是正常的成员函数,直接调用时遵循正常的 C++ 规则。但是,作为槽,任何组件都可以通过信号 - 槽连接调用它们,无论其访问级别如何。这意味着从任意类的实例发出的信号可以导致在不相关的类的实例中调用私有槽。
手动连接 :使用
QObject::connect
函数进行连接。例如:QObject::connect(&senderObject, &SenderClass::mySignal, &receiverObject, &ReceiverClass::mySlot);
自动连接 :在 Qt 的 UI 文件中定义的槽函数,可以通过
QMetaObject::connectSlotsByName
方法进行自动连接。例如,在 UI 文件中定义的槽函数on_pushButton_clicked()
,会自动与按钮的clicked
信号连接。需要注意的是,只有调用了QMetaObject::connectSlotsByName
方法后,这种形式的槽函数才有效,而在ui->setupUi(this)
中会调用它。五、信号与槽的连接类型及规则
连接类型 :主要讨论发送信号的对象和调用槽函数的对象是否在同一个线程中。常见的连接类型有自动连接、直接连接、排队连接、阻塞排队连接等。
连接规则 :信号的参数可以比槽函数多,反之则不可以;一个信号可以连接到多个槽;多个信号可以连接到同一个槽;信号还可以与另一个信号连接。
条件 :自定义信号与槽的类必须直接或间接继承自
QObject
;在类最开始的地方有Q_OBJECT
宏;有slots
关键字定义槽;有signals
关键字定义信号。示例代码 :
#ifndef SIGNALANDSLOT_H #define SIGNALANDSLOT_H #include <QObject> class SignalAndSlot : public QObject { Q_OBJECT public: explicit SignalAndSlot(QObject *parent = nullptr); signals: void mySignal(); public slots: void slotfun(); }; #endif // SIGNALANDSLOT_H
#include "signalAndSlot.h" #include <QDebug> SignalAndSlot::SignalAndSlot(QObject *parent) : QObject{parent} { } void SignalAndSlot::slotfun() { qDebug() << "execute slotfun"; }
七、Meta-Object Compiler (moc)
作用 :moc 是处理 Qt C++ 扩展的程序。它读取 C++ 头文件,如果找到包含
Q_OBJECT
宏的类声明,就会生成一个 C++ 源文件,其中包含这些类的元对象代码。元对象代码是信号和槽机制、运行时类型信息和动态属性系统所必需的。工作原理 :当使用
Q_OBJECT
宏时,moc 会为类生成额外的代码,这些代码实现了信号和槽的连接、类型信息的获取等功能。在编译过程中,moc 生成的代码会被编译进项目中,从而使得信号和槽机制能够正常工作。优点 :信号与槽机制提供了对象间通信的松耦合方式,使得代码更加模块化和易于维护。它简化了事件处理和数据交互的实现,提高了开发效率。
缺点 :由于信号和槽的连接是基于字符串匹配的,所以在编译时无法检查信号和槽的拼写错误,可能会导致运行时错误。此外,信号和槽的连接也可能导致代码的可读性降低,尤其是当连接很多时。
应用 :在实际开发中,信号与槽机制在 GUI 应用程序中非常有用。例如,按钮的点击事件可以通过信号与槽机制触发相应的处理函数。同时,它也可以用于非 GUI 应用程序中的对象间通信,如线程间的通信、组件间的协作等。
优化与改进 :为了提高信号与槽的可读性和可维护性,可以使用命名规范来定义信号和槽,避免使用模糊的名称。此外,可以使用智能指针来管理对象的生命周期,防止信号与槽连接中的悬挂指针问题。