Qt信号与槽机制是Qt框架中的一项重要特性,用于实现对象间的通信和事件处理。它是一种基于观察者模式(Observer Pattern)的设计模式。
在Qt中,对象可以通过信号和槽进行通信。信号是对象发出的通知,槽是接收信号的对象中的函数。当一个对象发出信号时,与之关联的槽会被调用,实现了对象间的松散耦合通信。
以下是关于Qt信号和槽机制的基本解释:
1. 信号(signal): 所谓信号槽(观察者模式),信号本质是事件,发生事件之后,则发出一个信号;
2.槽函数(slot): 对信号响应的函数,槽就是函数
1. 声明信号和槽:
在Qt中,使用`signals`关键字声明信号,使用`slots`关键字声明槽。信号和槽必须位于类定义的`signals`和`slots`部分,并且可以具有参数。
示例:```cpp
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = nullptr);
signals:
void mySignal(int value); // 声明一个带有整数参数的信号
public slots: //public slots: / protected slots: /private slots:
void mySlot(); // 声明一个无参数的槽
};
2. 连接信号和槽:
使用`QObject::connect`函数将信号连接到槽,建立信号和槽之间的关联。连接可以在应用程序代码中的任何地方完成,将发出信号的对象和接收信号的对象作为参数传递。
示例:cpp
MyObject *obj1 = new MyObject();
MyObject *obj2 = new MyObject();
QObject::connect(obj1, &MyObject::mySignal, obj2, &MyObject::mySlot);
3. 发出信号:
使用`emit`关键字发出信号。当某种条件满足时,在合适的地方使用`emit`关键字调用信号,将信号传递给与之连接的槽。
示例:cpp
void MyObject::myMethod()
{
// 满足某个条件后发出信号
if (condition)
emit mySignal(value);
}
4. 槽函数:
槽函数是接收信号的对象中的函数。当与之连接的信号被发出时,相应的槽函数会被调用进行处理。(槽函数是普通成员函数,会受到public protected private 的影响)
示例:cpp
void MyObject::mySlot()
{
// 处理信号的槽函数
}
通过信号和槽机制,可以实现对象间的通信和事件处理,而无需显式地依赖于对象的具体实现。这种松散耦合的通信方式提高了代码的可维护性和可扩展性。
需要注意的是,在使用信号和槽机制之前,类定义必须包含`Q_OBJECT`宏以启用Qt的元对象系统(Meta-Object System)对信号和槽的支持。
5. 信号与槽机制连接方式
一个信号和另一个信号连接;
connect(obj1,SIGNAL(signal1()),obj2,SLOT(signal1()));
同一个信号可以和多个槽连接;
connect(obj1,SIGNAL(signal2()),obj2,SLOT(signal2()));
connect(obj1,SIGNAL(signal2()),obj3,SLOT(signal1()));
同一个槽可以响应多个信号;
connect(obj1,SIGNAL(signal2()),obj2,SLOT(slots2()));
connect(obj3,SIGNAL(signal2()),obj2,SLOT(slots2()));
常用的连接方案采用:
/*
这里使用了SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串。注意到
connect()函数的 signal 和 slot 都是接受字符串,一旦出现连接不成功的情
况,Qt4是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否
匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。
*/
connect(obj1,SIGNAL(signal()),obj2,SLOT(slot()));
//Qt5 的写法 编译期间检查类型是否匹配
QObject::connect(obj1, &MyObject::mySignal, obj2, &MyObject::mySlot);
//若遇到信号和槽函数重载 则可利用函数指针的方式进行传参
//返回值 函数指针 参数列表
void (MyObject::*mySignal)(QString) = &MyObject::mySignal;
void (MyObject::*mySlot)(QString) = &MyObject::mySlot;
QObject::connect(obj1, mySignal, obj2, mySlot);
注意:信号函数的参数可以少于槽的参数(但是槽的参数绝对不能少于信号的参数)
C++11中的Lambda表达式用于定义并创建匿名函数对象,简化编程
6. Qt信号槽机制不支持对模板的使用
7. 信号与槽机制效率:增强对象之间的灵活性,但是也会损失一些性能,通过传递一个信号来调用槽函数将会比直接调用非虚函数运行速度慢;主要原因如下:
1. 多线程,信号可能需要排队等待;
2.编组/解组传递的参数;
3.安全的遍历所有关联;
4.需要定位接收信号对象;