QT的信号与槽机制是QT的核心机制,应用于对象间的同步或异步通信。要使用QT的信号与槽,需要使用QT提供的MOC工具。使用QT提供的元对象系统,需要定义两方面内容:
- 类直接或间接继承QObject
- 类中引用Q_OBJECT宏
信号与槽的使用,使得对象间变成松耦合。对象发送信号,并不知道另一端是哪个对象在连接这个信号。槽函数接收信号,它是普通的成员函数,并不知道有信号连接。如此,两个对象间完全独立。
一个信号可以连接多个槽函数,槽函数执行顺序就是连接顺序。信号还可以连接另外一个信号,使得信号可以触发其他信号。另外信号发出后,槽函数还可以选择进行同步或异步执行,方便进行程序设计。
在类中声明信号,可以用singnals关键字或Q_SIGNALS宏。声明槽函数,可以用slots关键字或Q_SLOTS宏。槽函数权限可以设置public,protected或private,意义和C++的权限设置一致。
信号与槽的连接
有两种连接方式
connect(this,SIGNAL(SubWidget(int)),sub_widget,SLOT(OnSubWidget1(int)));
connect(this,&QtDemo::SubWidget,sub_widget,&QtSubWidget::OnSubWidget1);
方法1需要增加函数参数,方法2省略。如果槽函数涉及到函数重载,需要使用方法1进行信号和槽连接,方法2编译器无法知道具体连接的哪个函数
信号的参数要大于等于槽函数的参数个数,但是参数的数据类型和顺序要一致,否则无法连接。意思就是信号可以提供多个参数,但是槽函数可以选择使用前几个参数,而不是全部使用。此类似http网络通信中,URL中可以提供多个参数,但是后端响应函数可以只使用其中的某几个参数,区别是响应函数的参数可以不按顺序。
信号和槽函数的返回值可以不一致,以信号的返回值为准。
信号和槽函数都可以附带默认参数,但连接的时候要注意明确连接的槽函数要唯一,不能产生二义性。
嵌套类不支持QT的元对象系统,无法使用信号和槽机制。
使用自定义数据类型作为信号和槽函数参数的时候,需要提前进行类型注册,使用
qRegisterMetaType<MSG>("MSG");
connect最后一个参数说明,控制槽函数的同步或异步调用
enum ConnectionType {
AutoConnection,
DirectConnection,
QueuedConnection,
BlockingQueuedConnection,
UniqueConnection = 0x80
};
Qt::AutoConnection,默认参数,如果在同一个线程,连接方式是DirectConnection,如果不在同一个线程,连接方式是QueuedConnection
Qt::DirectConnection,同步调用,emit后进入槽函数内部执行,执行之后返回,槽函数在信号线程内执行。
Qt::QueuedConnection,异步执行,emit后直接返回,下一个事件循环再执行槽函数,信号和槽可以在同一个线程,也可以在不同线程。
Qt::BlockingQueuedConnection,阻塞执行,在槽函数在不同线程的时候,执行完槽函数再返回。注意不要在信号和槽在同一个线程的时候使用,会导致程序产生死锁。
Qt::UniqueConnection,如果信号和槽已经连接过了,就不再连接了。
信号的发送
使用emit发送信号,可以同时获取返回值。
bool b = false;
emit(b = this->SubWidget(1, 2, 3, 5));
信号与槽的断开
disconnect(this,SIGNAL(SubWidget(int)),sub_widget,SLOT(OnSubWidget1(int)));
disconnect(this,&QtDemo::SubWidget,sub_widget,&QtSubWidget::OnSubWidget1);
也可以使用通配符0
disconnect(this, 0, 0, 0); // 断开this和所有对象的所有信号和关联槽
disconnect(this, 0, sub_widget, 0); // 断开this和sub_widget的所有信号和关联槽