学习QT之信号槽机制详解


一、Qt信号槽机制

概念:信号槽是Qt框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如:按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,他就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,放信号发出是,被连接的槽函数会自动被回调。

槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是共有的、保护的、私有的、也可以被其它C++成员函数调用。唯一的区别是:槽可以和信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽。

自定义信号槽注意事项

  1. 发送者和接受者都需要是QObject的子类(当然,槽函数是全局函数,Lambda表达式等无需接收者的时候除外);
  2. 使用signals标记信号函数,信号是一个函数声明,返回void,不需要实现函数代码;
  3. 槽函数是普通的成员函数,作为成员函数,会受到public、private、protected的影响;
  4. 使用emit在恰当的位置发送信号;
  5. 使用QObject::connect()函数连接信号和槽;
  6. 任何成员函数、static函数、全局函数和Lambda表达式都可以作为槽函数。

信号槽的多种用法

  1. 一个信号可以和多个槽相连;如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的。
  2. 多个信号可以连接到一个槽;只要任意一个信号发出,这个槽就会被调用。
  3. 一个信号可以连接到另一个信号;当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。
  4. 槽可以被取消连接;这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。
  5. 使用Lambda表达式;在使用Qt5的时候,能够支持Qt5的编译器都是支持Lambda表达式的。

二、QT信号槽机制的优缺点

(1)问题:为什么Qt使用信号与槽机制而不是传统的回调函数机制进行对象间的通信呢?

回调函数的本质是“你想让 别人的代码执行你的代码,而别人的代码你又不能动”这种需求下产生的。回调函数是函数指针的一种用法,如果多个类都关注某个类的状态变化,此时需要维护一个列表,以存放多个回调函数的地址。对于每一个被关注的类,都需要做类似的工作,因此这种做法效率低,不灵活。

(2)解决办法

Qt使用信号槽机制来解决这个问题,程序只需要指定一个类含哪些信号函数,哪些槽函数,Qt会处理信号函数和槽函数之间的绑定。当信号函数被调用时,Qt会找到并执行与其绑定的槽函数。允许一个信号函数和多个槽函数绑定,Qt会依次找到并执行与一个信号函数绑定的所有槽函数,这种处理方式更灵活。

(3)优点

Qt信号与槽机制降低了Qt对象的耦合度。

激发信号的Qt对象无须知道是哪个对象的哪个槽函数需要接收它发出的信号,它只需要做的是在适当的时间发送适当的信号就可以了,而不需要知道也不关心它的信号有没有被接收到,更不需要知道哪个对象的哪个槽接收了信号。

同样,对象的槽也不知道是哪些信号关联了自己,而一旦关联信号和槽,Qt就保证了适合的槽得到了调用。即使关联的对象在运行时被删除。应用程序也不会奔溃。

(4)缺点

信号槽机制,同回调函数相比,信号和槽机制运行速度有些慢。通过传递一个信号来调用槽函数将会比直接调用非虚函数运行速度慢10倍。原因如下:- 需要定位接收信号的对象;- 安全地遍历所有的关联(一个信号关联多个槽的情况);- 编组/解组传递的参数;- 多线程的时候,信号可能需要排队等待。

三、多线程情况下,Qt中的信号槽分别在什么线程中执行,如何控制?

通过connect()函数的第五个参数connectType来控制。

connect()用于连接Qt的信号和槽,在Qt编程过程中不可或缺。它其实有第五个参数,只是一般使用默认值,在满足某些特殊需求的时候可能需要手动设置。

Qt::AutoConnection:默认值,使用这个值则连接类型会在信号发送是决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在同一个线程,则自动使用Qt::QueuedConnection类型。

Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数运行与信号发送者所在线程。效果看上去就像是直接信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成崩溃。

Qt::QueuedConnection:槽函数在控制回到接受者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个。

Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。

Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接是,在进行复杂的了解就会失败。也就是避免了重复连接。

学习QT之信号槽机制详解相关推荐

  1. Qt信号槽机制详解及案例

    目录 信号槽 标准信号槽 自定义信号槽 信号槽 信号槽是Qt框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signa ...

  2. Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)

    转载地址: https://blog.csdn.net/nicai888/article/details/51169520 一 闲谈: 熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说: ...

  3. Qt的信号槽机制介绍

    Qt 是一个跨平台的 C++ GUI 应用构架,它提供了丰富的窗口部件集,具有面向对象.易于扩展.真正的组件编程等特点,更为引人注目的是目前 Linux 上最为流行的 KDE 桌面环境就是建立在 Qt ...

  4. Qt信号与槽机制详解1-创建一个带信号和槽的例子

    目录 一.编译一个例子 1.hello.h中的内容 2.hello.cpp的内容 3.main.cpp中的内容 4.tutorial.pro内容 二.moc_hello.cpp文件 1.Q_OBJEC ...

  5. Qt中事件循环机制详解

    问题1:Qt中常见的事件有哪些? 答:鼠标事件(QMouseEvent).键盘事件(QKeyEvent).绘制事件(QPaintEvent).窗口尺寸改变(QResizeEvent).滚动事件(QSc ...

  6. C++框架_之Qt的信号和槽的详解

    目录 C++_之Qt的信号和槽的详解 1.概述 1.1对象树(子对象动态分配空间不需要释放) 2.信号和槽 Qt5 的书写方式:(推荐的使用)★★★★★ Qt4 的书写方式: 3.自定义信号槽 3.1 ...

  7. 存储之Block-MultiQueue机制详解(二)

    1.首先看一下blk-mq的处理流程图(不同内核版本之间会有一些差异,但整体结构基本一样) 从整个流程图可以看到,主要是分为三个部分:(1)初始化硬件设备的相关参数(2)初始化请求队列request_ ...

  8. Qt之信号signals和槽slots详解

    学习到自定义信号和槽的时候经常编译不过去,前边一篇解决了Q_OBJECT编译的问题,这里详细说明了slots和signals. 1.signals前面不可加public.private和protect ...

  9. 【QT|趣谈】最详细的信号槽机制介绍!

    用最有趣的方式解释信号槽通讯机制 1 导语:信号槽的前世今生 2 QT的信号槽 2.1什么是信号槽? 2.2 用严谨的语言解释信号槽 3 信号槽实战 3.1 信号槽实例 4 信号槽plus 4.1 L ...

最新文章

  1. 综述|核心开发者全面解读Pytorch内部机制
  2. 第3章 View的事件体系
  3. 微信看一看实时相关推荐介绍
  4. sharepoint数据库连接
  5. git学习(四):理解git暂存区(stage)
  6. 电商场景下,如何处理消费过程中的重复消息?
  7. 压测工具下载地址说明及汇总
  8. 谷歌大脑AutoML最新进展:不断进化的阿米巴网络
  9. windows 2008 server 各版本功能差异
  10. FlexForAndroid:文件读写
  11. android 7双排设置菜单,双排状态栏
  12. 分享几个纯净版Windows系统下载网站
  13. 2020-12-06 高等数学:常用积分公式
  14. masquerade词根词缀_词根词缀总结
  15. OSChina 周三乱弹 —— 我在 if 里,你却在 else
  16. ajax 与form 表单连用 success不执行bug解决
  17. VM 虚拟机屏幕大小的调整
  18. 计算机防火墙不能更改,win7无法更改防火墙设置提示系统报错怎么办
  19. PTA L1-057 PTA使我精神焕发 C++实现
  20. 面向对象A类实验题目:排序

热门文章

  1. Lambda表达式与匿名内部类
  2. 2021全国大学生数学建模B题 乙醇偶合制备 C4 烯烃
  3. Makefile中patsubst函数使用方法
  4. matlab实现CRC_16,关于CRC校验实现程序解释(CRC16为例)
  5. java黑名单校验_短信验证码被刷怎么办?java 短信验证码防刷策略
  6. Mac-brew报错error: could not lock config file .git/config: Permission denied
  7. LarduinoISP for LGT8FX8D SWD通信协议源码简析
  8. 计算机基础知识文字处理系统,计算机基础知识文字处理.ppt
  9. mysql中condition的用法,mybatis的condition使用
  10. 2023年税务师事务所行业研究报告