信号槽 与事件区别

转自网络

仔细来看,事件与信号其实并无多大差别,从我们对其需求上来说,都只要能注册事件或信号响应函数,在事件或信号产生时能够被通知到即可。但有一项区别在 于,事件处理函数的返回值是有意义的,我们要根据这个返回值来确定是否还要继续事件的处理,比如在QT中,事件处理函数如果返回true,则这个事件处理 已完成,QApplication会接着处理下一个事件,而如果返回false,那么事件分派函数会继续向上寻找下一个可以处理该事件的注册方法。信号处 理函数的返回值对信号分派器来说是无意义的。

另外还有一个需要我们关注的问题是事件和信号处理时的优先级问题。在QT中,事件因为都是与窗口相关的,所以事件回调时都是从当前窗口开始,一级一级向上 派发,直到有一个窗口返回true,截断了事件的处理为止。对于信号的处理则比较简单,默认是没有顺序的,如果需要明确的顺序,可以在信号注册时显示地指 明槽的位置。

在QT中,事件使用了一个事件队列来维护,如果事件的处理中又产生了新的事件,那么新的事件会加入到队列尾,直到当前事件处理完毕后, QApplication再去队列头取下一个事件来处理。而信号的处理方式有些不同,信号处理是立即回调的,也就是一个信号产生后,他上面所注册的所有槽 都会立即被回调。这样就会产生一个递归调用的问题,比如某个信号处理器中又产生了一个信号,会使得信号的处理像一棵树一样的展开。

评价:实际上信号-槽也可以异步的,这个bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoCompatConnection )
里面的Qt::AutoCompatConnection,可以根据实际情况确定

所有使用了信号和槽的类都必须包含 Q_OBJECT 宏,而且这个类必须从QObject类派生(直接或者间接派生)出来,
    当一个signal被emit出来的时候,链接到这个signal的slot会立刻被调用,就好像是一个函数调用一样。当这件事情发生的时 候,signal和slot机制与GUI的事件循环完全没有关系,当所有链接到这个signal的slot执行完成之后,在 emit 代码行之后的代码会立刻被执行。当有多个slot链接到一个signal的时候,这些slot会一个接着一个的、以随机的顺序被执行。
    Signal 代码会由 moc 自动生成,开发人员一定不能在自己的C++代码中实现它,并且,它永远都不能有返回值。
    Slot其实就是一个普通的类函数,并且可以被直接调用,唯一特殊的地方是它可以与signal相链接。
    C++的预处理器更改或者删除 signal, slot, emit 关键字,所以,对于C++编译器来说,它处理的是标准的C++源文件。

signal/slot 在底层会使用三种方式传递消息。bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoCompatConnection )
最后一个参数是就是传递消息的方式了,有四个取值:

1.Qt::DirectConnection
When emitted, the signal is immediately delivered to the slot.
假设当前有4个slot连接到QPushButton::clicked(bool),当按钮被按下时,QT就把这4个slot按连接的时间顺序调用一遍。显然这种方式不能跨线程(传递消息)。

2.Qt::QueuedConnection
When emitted, the signal is queued until the event loop is able to deliver it to the slot.
假 设当前有4个slot连接到QPushButton::clicked(bool),当按钮被按下时,QT就把这个signal包装成一个 QEvent,放到消息队列里。QApplication::exec()或者线程的QThread::exec()会从消息队列里取消息,然后调用 signal关联的几个slot。这种方式既可以在线程内传递消息,也可以跨线程传递消息。

3.Qt::BlockingQueuedConnection
Same as QueuedConnection, except that the current thread blocks until the slot has been delivered. This connection type should only be used for receivers in a different thread. Note that misuse of this type can lead to dead locks in your application.
与Qt::QueuedConnection类似,但是会阻塞等到关联的slot都被执行。这里出现了阻塞这个词,说明它是专门用来多线程间传递消息的。

4.

Qt::AutoConnection
If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt::DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection.
这种连接类型根据signal和slot是否在同一个线程里自动选择Qt::DirectConnection或Qt::QueuedConnection

这样看来,第一种类型的效率肯定比第二种高,毕竟第二种方式需要将消息存储到队列,而且可能会涉及到大对象的复制(考虑sig_produced(BigObject bo),bo需要复制到队列里)。

Qt的线程和 signal-slot

再问coredump或者QT高手们一个问题。QT里用线程,主线程是GUI,次线程是工作线程,如果次线程里也用消息循环(exec),即,主/次间用signal-slot通讯来实现同步,在这种情况下, 1.主线程会被次线程block吗? 2.如果在单cpu里会被block吗,如果次线程里不断循环,低层会自动分配时间片给主线程吗? 3.这种方法和直接调用次线程中的方法,用mutex之类的来实现类似的循环,效率差别大吗?记得QT里讲过signal-slot只是多几个函数调用的差别。 呵呵,问的不太清楚,主要就是想问一下,主次线程中怎样通讯比较有效。 谢谢阿。

QThread 现在默认状态下就是有一个消息循环的,而且鼓励使用线程独立的消息循环 1.主线程会被次线程block吗? 不会,QObject::connectd的最后一个参数默认使用Qt::AutoConnection, 在多线程环境下,会自动选择Qt::QueuedConnection方式,除非强制使用Qt::BlockingQueuedConnection或者 Qt::DirectConnection, 否则线程不会block. 2.如果在单cpu里会被block吗,如果次线程里不断循环,低层会自动分配时间片给主线程吗? 线程和CPU个数没有关系,当然CPU多了,运行会更加流程,线程的资源分配(时间片)是由操作系统管理的,在各个系统上都是如此 3.这种方法和直接调用次线程中的方法,用mutex之类的来实现类似的循环,效率差别大吗? 执行效率上很难讲,但是mutex肯定是带来了开发效率的降低,你得小心翼翼地处理好各种临界资源的锁问题 4. 记得QT里讲过signal-slot只是多几个函数调用的差别 是的,signal-slot的这种轻微的效率损失在绝大多数情况下不是问题,除非过度使用,这一般是设计上的错误导致的 分享两篇文章,讲QThread和Qt的signal-slot的: 1篇是qt labs的博客上一篇 You are doing it wrong...(http://labs.trolltech.com/blogs/2010/06/17/youre-doing-it-wrong/), 这篇文章很有意思,其实很多人不知道原来QThread还可以这样用。 另外一篇是关于怎么利用Qt的signal-slot机制和QThread进行完全的lock free编程(http://thesmithfam.org/blog/2009 ... ti-threading-in-qt/)

多谢多谢,再学习去。 之所以问,是因为,我做了一个下载googlemap的程序,开始下载线程后,GUI就不动了,直到下载结束。虽然操作系统会分配时间,但是如果下载线程循环,而且优先级相同的话,是不是还是有影响?

我再看看哪里出问题了。 刚看了你上面的两个链接,真是切中要害阿,呵呵,一直就在琢磨这个一段时间了。 总结一下理解,看看对不对。 第一篇里,QThread里默认的run()已经启动了消息循环exec(). 当需要新线程时,应该,直接生成QThread, start()。至于功能,应该放在另外的类里,在调用start前设置好signal-slot,再moveToThread到 QThread中。 不用sunbclass QThread。 我一直或者重新实现run(),在run()里生成所有object, signal-slot, 或者如文中所说的QThread.moveToThread(QThread). 这两种都有不少问题,破坏OO的概念。 很清楚。

第二篇里讲了用线程间的signal-slot来同步,正好回答了之前的疑问,不过他使用qthread的方法恰恰违背了第一篇的思想。

引用:

原帖由 GPS 于 12-7-2010 12:40 发表  我再看看哪里出问题了。 刚看了你上面的两个链接,真是切中要害阿,呵呵,一直就在琢磨这个一段时间了。 总结一下理解,看看对不对。 第一篇里,QThread里默认的run()已经启动了消息循环exec(). 当需要新线程时 ...

另一种方式也不错,有些情况下必须subclass QThread, 错的不是是否subclass,错在:subclassing QThread, adding signal and slot code to that subclass, and then calling moveToThread(this);

引用:

To set the record straight: I’m not saying sub-classing QThread is wrong. This is also how Java does it (sort of), and many people have been doing this with Qt for a long time. What I’m saying is “wrong” is subclassing QThread, adding signal and slot code to that subclass, and then calling moveToThread(this); in the constructor of that subclass. This causes people lots of confusion from my experience and observation on the #qt channel and the qt-interest mailing list. And yes, the current docs are still a bit lacking, something that I am fully aware of (and take responsibility for). I’m planning on sitting down and fleshing them out, showing both ways of using QThread (with and without subclassing).

在Qt的编程模型里,thread和signal- slot都是实现异步编程的手段,signal-slot的背后是消息循环,而每个thread都是一个独立的消息循环,在早期版本,qt线程间无法进行 signal-slot消息传递,这就导致了各个消息循环都是互相独立的loop, 通讯的唯一方式只剩下global state+ mutex lock。在4.x 之后,signal-slot已经能够和thread融洽相处了。 这样,理想的QT编程模型就变成了独立的一个个任务,各自 使用自己的thread和thread内部消息循环,在需要互相通讯的时候,使用signal-slot, 这些signal和slot就是明确定义的消息接口,除此之外,最好不共享其它状态。Qt程序员有点像转盘子的杂技演员,每个盘子都独自转动,整个系统由 很多旋转的盘子组成,这些盘子可以共享杂技演员一个手,也可以是另一只手甚至不同的杂技演员来控制(多CPU)

时间: 2024-09-29 01:50:58

信号槽 与事件区别的相关文章

Qt高级——Qt信号槽机制源码解析

Qt高级--Qt信号槽机制源码解析 基于Qt4.8.6版本 一.信号槽机制的原理 1.信号槽简介 信号槽是观察者模式的一种实现,特性如下:A.一个信号就是一个能够被观察的事件,或者至少是事件已经发生的一种通知:B.一个槽就是一个观察者,通常就是在被观察的对象发生改变的时候--也可以说是信号发出的时候--被调用的函数:C.信号与槽的连接,形成一种观察者-被观察者的关系:D.当事件或者状态发生改变的时候,信号就会被发出:同时,信号发出者有义务调用所有注册的对这个事件(信号)感兴趣的函数(槽).信号和

PyQt5快速入门(二)PyQt5信号槽机制

PyQt5快速入门(二)PyQt5信号槽机制 一.信号槽机制简介 1.信号槽简介 信号槽是Qt的核心机制,也是PyQt编程中对象进行通信的机制.在Qt中,QObject对象和PyQt中所有继承自QWidget的控件都支持信号槽机制.当信号发射时,连接的槽函数会自动执行.在PyQt5中,信号与槽函数通过object.signal.connect()方法进行连接.信号槽特点如下:(1)一个信号可以连接多个槽(2)一个信号可以连接另一个信号(3)信号参数可以是任意Python类型(4)一个槽可以监听多

Qt信号槽机制源码解析

Qt信号槽机制源码解析 来源 https://blog.51cto.com/9291927/2070398 一.信号槽机制的原理 1.信号槽简介 信号槽是观察者模式的一种实现,特性如下:A.一个信号就是一个能够被观察的事件,或者至少是事件已经发生的一种通知:B.一个槽就是一个观察者,通常就是在被观察的对象发生改变的时候——也可以说是信号发出的时候——被调用的函数:C.信号与槽的连接,形成一种观察者-被观察者的关系:D.当事件或者状态发生改变的时候,信号就会被发出:同时,信号发出者有义务调用所有注

QT信号槽与Delphi事件的对比

最近学QT,对信号槽机制感到有点新鲜: QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int))); 自己总结其原理,就是一句话:把两个对象的函数相关(往往是设置同一个值),而不用考虑两个对象之间的关系,而且可以一对多发信号.缺点是,事先要规定哪些函数可以信号,哪些函数是槽.而且执行内容貌似有点单调. 这一机制号称先进,但Delphi里其实也有,而且应该更强大,因为信号源可以任意指定.而且设计时可以,动

我的QT5学习之路(四)——信号槽

一.前言 前面说了Qt最基本的实例创建.控件以及工具集的介绍,相当于对于Qt有了一个初次的认识,这次我们开始认识Qt信号通信的重点之一——信号槽. 二.信号槽 信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal).这种发出是没有目的的,类似广播.如果有对象对这个信号感兴趣,它就会使用连接(connect)

Qt 学习之路 :信号槽

信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal).这种发出是没有目的的,类似广播.如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,用自己的一个函数(成为槽(slot))来处理这个信号.也就是说,当信号发出时,被连接的槽函数会自动被回调.这就类似观察者模式:当发生了感兴趣的事件

Qt Connect 信号 槽

信号和槽机制是 QT 的核心机制 .信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方.信号和槽是 QT 自行定义的一种通信机制,它独立于标准的 C/C++ 语言,因此要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler)的 QT 工具,该工具是一个 C++ 预处理程序,它为高层次的事件处理自动生成所需要的附加代码.  在QT中,connect()函数是关联部件的动作与执行的函数. 在启动函数中进行设置

PyQt5学习笔记05----Qt Designer信号槽

先入一些信号槽的基本介绍: 信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方.它为高层次的事件处理自动生成所需要的附加代码.在我们所熟知的很多 GUI 工具包中,窗口小部件 (widget) 都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指针.但是,在 QT 中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了. 所有从 QObject 或其子类 ( 例如 Qwidget) 派生的

[转]深入理解信号槽机制

原文不可考 来源链接http://blog.csdn.net/liuuze5/article/details/53523463 深入理解信号槽(一) 这篇文章来自于 A Deeper Look at Signals and Slots,Scott Collins 2005.12.19.需要说明的是,我们这里所说的"信号槽"不仅仅是指 Qt 库里面的信号槽,而是站在一个全局的高度,从系统的角度来理解信号槽.所以在这篇文章中,Qt 信号槽仅仅作为一种实现来介绍,我们还将介绍另外一种信号槽的