目录
信号和槽
作为qt核心机制之一,是为了满足对象间的通信。
简述
Qt的信号槽机制的底层实现其实是基于观察者模式。
举个栗子,点击按钮-->发射信号-->connect-->调用槽函数-->实现功能,这个简单的过程就通过信号槽机制,来满足我们两对象间的功能。显然,在过程中需要由信号发送者-->发送信号-->接收者-->执行槽(发送者拥有信号,接收者拥有槽)。
使用信号和槽时,注意两点:
①类要直接/间接继承QObject类;
②要在类首行使用宏Q_OBJECT ;
自定义信号
声明信号要使用signals关键字;
只声明,不定义实现;
没有返回值。只能是void类型;
signals:
void Signal();
发射信号
需在槽中使用关键字 emit 信号();
emit Signal();
槽
权限+slots,需要声明和实现;
也能被声明为虚函数,也可像调用普通函数一样来调用槽。
private slots:
void Slot();
connect关联函数
结构如下:
connect(信号发送者,信号,信号接收者,槽,连接方式);
在Qt信号槽中,关联函数connect有四种写法;
1,宏定义
因为宏定义在预处理阶段完成,所以在使用SIGNAL和SLOT两个宏时,在编译阶段无法进行类型检查,也会忽略槽的权限,是不安全的。
connect(信号发送者,SIGNAL(信号(参数类型)),信号接收者,SLOT(槽(参数类型)),连接方式);
2,信号/槽无重载时,使用一般的函数指针
会有类型检查,但是遇到函数名相同时,编译会报错,只能用于信号或槽无重载时使用,也是不安全的。
connect(信号发送者,&类名::信号名,信号接收者,&类名::槽名,连接方式);
3,若信号/槽重载时,用QOverload来加载函数指针
具体指定了那种参数的函数,避免了不知道是哪个同名函数的题,是安全的。
connect(信号发送者,QOverload<形参类型>::of(&类名::信号名),信号接收者,QOverload<形参类型>::of(&类名::槽名),连接方式);
4,使用匿名函数lambda表达式取来槽函数
connect(信号发送者,QOverload<形参类型>::of(&类名::信号名),信号接收者,[](形参列表){},连接方式);
连接方式5种
上面提过Qt信号槽连接的函数connet函数,共五个参数,第五个为连接方式;默认情况下,第五个参数不用写,使用的为自动连接的缺省值。在当使用自动连接的时候,单线程中,会自动切换到直接连接,多线程时会切换到队列连接。
1,自动连接
会根据线程来自动切换。单线程下,直接连接;多线程下,队列连接。
connect(信号发送者,信号,信号接收者,槽,Qt::AutoConnection);
2,直接连接
发射完信号后立即执行槽,只有槽执行完成返回后,发射信号处后面的代码才执行。单线程时使用,同步阻塞执行。
connect(信号发送者,信号,信号接收者,槽,Qt::DirectConnection);
3,队列连接
接收部件所在线程的事件循环返回后再执行槽,无论槽执行与否,发射信号后,立即执行发射信号后的代码。多线程,单线程都可以使用,异步非阻塞。
connect(信号发送者,信号,信号接收者,槽,Qt::QueuedConnection);
4,阻塞队列连接
类似队列连接,只在信号和槽在不同线程(多线程)的情况下使用。在多线程时使用,同步阻塞执行效果,若单线程,则会发生死锁。
connect(信号发送者,信号,信号接收者,槽,Qt::BlockingQueuedConnection);
5,唯一连接
类似自动连接,但两个对象间的相同信号和槽只能有唯一关联。主要用来防止槽的重复链接。
connect(信号发送者,信号,信号接收者,槽,Qt::UniqueConnection);
关于顺序问题
一个信号,多个槽:
在Qt4中,无序的,是随机执行;
在Qt5中,有序的,先关联的先执行。
多个槽,一个信号:
当关联的信号被发射后,都会执行。