Qt信号槽的五种连接方式

关于信号槽

信号槽是Qt框架的精髓,尤其是用写过win32 API的开发过的人,一下子发现能把程序不同模块快速解耦,当然是有一定的性能损失和额外的开销,但99%的情况桌面客户端目前可以不care这点事

Qt信号槽简介

信号

当某个QObject对象的“状态”发生了改变或需要“通知”其他的对象,这时通过emit的方式把信号和绑定的参数发送出去。

用于接收信号的成员函数,槽函数知道是谁触发了他,但并不知道有多少个信号与之绑定

链接方式

enum ConnectionType {
	AutoConnection,//默认
	DirectConnection,//立即调用
	QueuedConnection,//放在接收者队列
	BlockingQueuedConnection,//与放在接收者队列,同时阻塞发送者
	UniqueConnection =  0x80//标志位,避免重复链接
};

一次连接,终身调用,除非disconnect

connect五种连接方式的使用场景

使用场景和多线程有着弥补可分的关系,Qt的元对象系统本身在消息分发时就有线程的逻辑

connect 函数原型
[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
Qt::AutoConnection(默认)

根据 sender 和 receiver 两者所在线程,当信号发出时作出判断。同一线程则 Qt::DirectConnection 连接,否则使用 Qt::QueuedConnection 连接。容易产生误区的点:不是sender的所属线程,而是真正触发了emit 信号的动作线程。

Qt::DirectConnection

无论sender和receiver是否在统一线程,都会立刻调用槽函数,最简单的理解成把一段代码“临时插入”到了运行栈,所以在多线程情况下非常危险,必须做好线程同步。

Qt::QueuedConnection

sender的信号会被压入到接收者的事件循环中,所以不会立即调用。而是等到当接收者对象处理其自身的消息队列时,再针对消息队列中的这个信号进行处理。可以说就是为了开发者解决跨线程通信而设计的。当然你也可以用于同一个线程不同对象,这种相同线程的强行指定队列方式通常都会和GUI的模态窗有关(后面会举例分析)。

Qt::BlockingQueuedConnection

这个真的是看名字就知道干了啥,Blocking+QueuedConnection,这就说明他的槽函数运行时机与QueuedConnection是一致的。那Blocking的意义是什么?就是阻塞发送者!直到槽函数运行完毕再继续执行。源码上相比QueuedConnection的实现多加了一个等待输入的信号量QSemaphore,所以一旦接收者和发送者在同一线程,那势必就会差生死锁。

Qt::UniqueConnection

这个其实严格上来说相比上面四种方式并不算新的连接方式,而是用于修饰上面的四种连接方式。他实现的效果就是避免重复连接,因为Qt的信号槽是可以同一个信号和槽函数重复多次连接。这种通常都会是只执行一次就好,那就通过这个标志位进行修饰,达到多次连接(实际上也只是连接了一次)也只调用一次槽函数的效果。用(Qt::ConnectionType|Qt::UniqueConnection)来修饰。

connect(ui->btn_close, &QPushButton::clicked, this, &QWidget::close,Qt::DirectConnection|Qt::UniqueConnection)

后续

懂了以上,对于Qt开发新手基本够用。
接下来会用几篇进行Qt信号槽源码分析、Qt信号槽实现的分析、Qt信号槽实战的一些误区,因为只有明白了底层原理才能真正把信号槽用好。本身没啥写博客的经验,如果确实写的比较乱,请各位看过的大佬轻喷。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值