QT信号与槽

/ 0评 / 0

QT的信号与槽机制是QT的核心机制,应用于对象间的同步或异步通信。要使用QT的信号与槽,需要使用QT提供的MOC工具。使用QT提供的元对象系统,需要定义两方面内容:

信号与槽的使用,使得对象间变成松耦合。对象发送信号,并不知道另一端是哪个对象在连接这个信号。槽函数接收信号,它是普通的成员函数,并不知道有信号连接。如此,两个对象间完全独立。

一个信号可以连接多个槽函数,槽函数执行顺序就是连接顺序。信号还可以连接另外一个信号,使得信号可以触发其他信号。另外信号发出后,槽函数还可以选择进行同步或异步执行,方便进行程序设计。

在类中声明信号,可以用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的所有信号和关联槽