QT信号与槽机制与事件机制的区别

第一:什么是信号与槽?事件?

    所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,用自己的一个函数(成为槽(slot))来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。(这里提一句,Qt 的信号槽使用了额外的处理来实现,并不是 GoF 经典的观察者模式的实现方式。)

   事件(event)是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。事件也就是我们通常说的“事件驱动(event drive)”程序设计的基础概念。事件的出现,使得程序代码不会按照原始的线性顺序执行。

第二:信号与槽的作用是什么?事件呢?

   信号与槽的是针对类对象来使用的,当一个对象有一个信号的动作时,通过信号槽的方式可以将此信号发送给connect关联的另一个类对象的槽函数。信号槽是线程安全的,同时对于信号和槽函数,他们的参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。一般来讲,信号槽在模块内进行使用。

  对于自定义信号,注意的是函数返回为void,同时不需要去实现它,QT的元对象系统会自动生成对应函数。而对于槽函数其实就跟不同函数一样,会受到public,private,protected的影响。

  事件其实也就是所谓的事件驱动,比如我们设计了一堆功能放在界面上,用户点击了“打开文件”,于是开始执行打开文件的操作;用户点击了“保存文件”,于是开始执行保存文件的操作。我们不知道用户究竟想进行什么操作,因此也就不能预测接下来将会调用哪一个函数。如果我们设计了一个“文件另存为”的操作,如果用户不点击,这个操作将永远不会被调用。这就是所谓的“事件驱动”,我们的程序的执行顺序不再是线性的,而是由一个个事件驱动着程序继续执行。没有事件,程序将阻塞在那里,不执行任何代码。

第三:信号/槽机制原理?事件机制的原理?

  首先需要了解元对象系统,为什么信号没有定义但却可以通过编译使用,原因就在于元对象系统,通过此,信号可以被定义,此时就已经知道信号的索引,通过此索引就能找到对应的槽函数。

事件机制通过使用一个事件队列对所有发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部。前一个事件完成后,取出后面的事件进行处理。但是,必要的时候,Qt 的事件也可以不进入事件队列,而是直接处理。需要了解的是所有的事件都有一个事件处理函数,这时我们需要通过event进行事件的分发。当然也可以使用事件过滤器用来模拟一种系统根本没有那个事件的效果。

第四:什么场景下需要用到信号与槽,什么场景下用事件机制?

 信号槽一般用于模块内进行通信,对于不同的类对象之间的联动处理需要使用此机制。

事件机制往往用于以下几种情形:

重写paintEvent()、mousePressEvent()等事件处理函数。这是最普通、最简单的形式,同时功能也最简单。
重写event()函数。event()函数是所有对象的事件入口,QObject和QWidget中的实现,默认是把事件传递给特定的事件处理函数。
在特定对象上面安装事件过滤器。该过滤器仅过滤该对象接收到的事件。
在QCoreApplication::instance()上面安装事件过滤器。该过滤器将过滤所有对象的所有事件,因此和notify()函数一样强大,但是它更灵活,因为可以安装多个过滤器。全局的事件过滤器可以看到 disabled 组件上面发出的鼠标事件。全局过滤器有一个问题:只能用在主线程。
重写QCoreApplication::notify()函数。这是最强大的,和全局事件过滤器一样提供完全控制,并且不受线程的限制。但是全局范围内只能有一个被使用(因为QCoreApplication是单例的)。

原文链接:https://blog.csdn.net/u011006800/article/details/84582981

posted on 2024-03-11 14:33  keleman  阅读(247)  评论(0编辑  收藏  举报