QT信号与槽详解

信号与槽的用法:
1.一个信号可以连接多个槽,同一线程槽函数执行顺序与连接顺序相关,跨线程时,执行顺序随机。
2.多个信号可以连接到一个槽,任意信号emit,槽函数被执行。
3.信号可以连接到另一个信号。
4.槽可以被取消链接,当一个对象delete后,Qt自动取消所有连接到这个对象的槽,主动取消链接用disconnect()函数。
5.使用lambda表达式。
6.connect的第5个参数。
1.默认值为AutoConnection:根据连接类型自动解析,若发送者和接收者在同一个线程,自动使用Qt::DirectConnection,若不在一个线程,自动使用Qt::QueuedConnection类型。
2.Qt::DirectConnection:槽函数在信号发出后直接被调用,两者在同一线程,emit后面的代码在槽函数执行后才被执行。
3.Qt::QueuedConnection:信号发出后被暂时放到一个消息队列中,等到接收对象所属的事件循环取得控制权时才获得该信号,然后执行和信号相关的槽函数,此方式可以在同一线程内传递消息也可以跨线程操作。
emit后的代码在发出信号后立即被执行,无需等待槽函数执行完毕。
4.Qt::BlockingQueuedConnection:槽函数调用时机与Qt::QueuedConnection一致,但发送完信号后发送者所在线程会被阻塞,直到槽函数执行结束,注意:发送者与接收者不能在同一线程,否则会死锁,多线程同步场合需要这个连接方式。
5.Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用,当flag被设置时,表示信号与槽已连接,重复连接会失败。此连接方式是为了避免重复连接。
获取信号发送者:
调用sender()函数获取发送对象的指针,返回QObject指针。QObject* sender();
解除绑定信号槽:
使用disconnect()函数进行解除绑定。
信号与槽的原理:基于moc元对象预编译七。
moc预编译器:
moc读取一个c++头文件,如果它找到包含Q_OBJECT宏的一个或多个类声明,会生成一个包含这些类的元对象代码的c++源文件,并且以moc_作为前缀。
信号和槽机制,运行时类型信息和动态属性系统需要元对象代码,由moc生成的c++源文件必须编译并与类的实现联系起来。moc不是手动调用的,而是由构建系统自动调用的,因此不需要程序员额外的工作。
Qt的元对象系统:信号槽,属性系统,运行时类信息都存储在静态对象staticMetaObject中。
moc查找头文件中的signals,slots,标记出信号与槽,将信号与槽信息储存到staticMetaObject中,并按声明顺序进行存放,建立索引,当调用emit时,调用信号函数,并且传递发送信号的对象指针,元对象指针,信号索引,参数列表到active函数,通过active函数找到在map中找到所有与信号对应的槽索引,根据索引找到槽函数后执行。
信号与槽的注意点:
1.槽的属性:
声明public:表明所有对象都可将信号与之连接。
声明protected:表明当前类及其子类能将信号与之连接。
声明private:表明只有类自己能将信号与之连接。
2.若发送者与接收者属于同一对象的话,在connect调用中接受者参数能省略。
3.以下三种情况可使用disconnect()函数:
1.断开某个对象相关联的所有对象,若某个对象中定义了一个或多个信号,这些信号和另外若干个对象中的槽相关联,断开这些关联可以用:

disconnect(myObject,0,0,0) 或 myObject->disconnect()
2.断开某个特定信号的所有关联。
disconnect(myObject,SIGNAL(mySignal()),0,0) 或 myObject->disconnect(mySignal())
3.断开两个对象的关联。
disconnect(myObject,0,myReceiver,0) 或 myObject->disconnect(myReceiver)
在disconnect函数中0能用作一个通配符,分别表示所有信号,所有接收对象,接收对象中的所有槽函数,但发送者sender不能为0,其他三个参数的值能等于0。

4.宏定义不能用在signal和slot的参数中。
因为moc工具不扩展#define,所以在signals和slots中携带参数的宏不能正确工作。

#define SIGNEDNESS(a) unsigned a
 		signals:
 			void testSignal(SIGNEDNESS(a))

5.构造函数不能用在signals或slots声明区域内。
6.函数指针不能作为信号槽的参数,可以用typedef,如:

typedef void (*ApplyFunctionType) (QList*,void*);
 		public slots:
 			void aoolySlot(ApplyFunctionType,char*);

7.信号和槽不能有缺省参数,signal和slot绑定是发生在运行时。
8.信号和槽不能携带模板类参数,可以用typedef取巧。

typedef pair IntPair;
 		public slots:
 			void setLocationSlot(IntPair location);

9.嵌套类不能位于信号和槽区域内,也不能有信号槽,如果类b嵌套在类a内,想在类b中声明信号与槽是不行的
10.友元声明不能位于信号与槽声明区内。
槽的执行时间大于信号发送间隔问题(两个问题):
1.若需要对每个发来的信号都做出处理,有两种方式解决,将connect函数中的第5个参数,将其设置成DirectConnection方式阻塞,或者设置成BlockingQueuedConnection阻塞。
2.若需要对最新的信号做处理,有两种方式处理:
a.槽所在线程设置bool状态,信号所在线程通过判定这个bool的状态来确定是否发送信号。
b.槽执行完毕,向信号所在线程发送返回值,信号所在线程通过判定发来的返回值判断是否对槽所在线程发送新的信号。
连接断开后,在此连接的方式:
使用阻塞或者断开信号槽的方法来处理。
阻塞方法:bool QObject::blockSignals(bool block);
在此模式下,这个对象发送的信号都会被阻塞,解除阻塞后则不再阻塞。
使用disconnect()函数断开,成功则返回true

你可能感兴趣的:(Qt,qt)