[Qt][信号与槽][下]详细讲解

目录


1.自定义信号和槽

1.基本语法

  • 在Qt中,允许⾃定义信号的发送⽅以及接收⽅,即可以⾃定义信号函数和槽函数
  • ⾃定义信号函数书写规范
    • ⾃定义信号函数必须写到"signals"下
    • 返回值为void,只需要声明,不需要实现
    • 可以有参数,可以发⽣重载
  • ⾃定义槽函数书写规范
    • 早期的Qt版本 要求槽函数必须写到"public slots"下
    • 现在⾼级版本的Qt 允许写到类的 "public" 作⽤域中或者全局下
    • 返回值为void,需要声明,也需要实现
    • 可以有参数,可以发⽣重载
  • 发送自定义信号 :
    • 使⽤"emit"关键字发送信号,"emit"是⼀个空的宏
    • "emit"其实是可选的,没有什么含义,只是为了提醒开发⼈员
      • 即 :即使不写emit,信号也能发出去
      • 但是建议实际开发中,加上emit,代码可读性高
    • 举例 :emit MySignal();

2.带参数的信号和槽

  • Qt的信号和槽也⽀持带有参数,同时也可以⽀持重载
  • 要求:信号函数的参数列表要和对应连接的槽函数列表一致
    • 此时信号触发,调⽤槽函数的时候,信号函数中的实参就能够被传递到槽函数的形参当中
    • 通过这样的机制,就可以让信号给槽传递数据了
  • 实际上,参数列表一致主要是要求类型一致,个数如果不一样也可以
    • 但是要求信号的参数的个数必须要比槽的参数的个数多
      • 个数不一致,槽函数会按照参数顺序,拿到信号的前N个参数
      • 确保参数的每个参数都是有值的
    • 为什么允许信号的参数比槽的参数多呢?
      • 一个槽函数,可能会绑定多个信号
        • 如果严格要求参数一致,就意味着信号绑定到槽的要求变高了
      • 这样的规则下,允许信号和槽之间的绑定更灵活了

2.信号与槽的连接方式

0.信号和槽存在的意义?

  • Qt信号槽connect这个机制,设想很美好
    • 解耦合:把触发用户操作的空间和处理对应用户的操作逻辑解耦合
    • "多对多"效果 <--
      • 一个信号,可以connect到多个槽函数上
      • 一个槽函数,也可以被多个信号connect
  • Qt引入信号槽最本质的初心 :让信号和槽之间按照"多对多"的方式进行关联
    • 实际上,很多时候,"多对多"这件事,其实是个"伪需求",实际开发很少会用到

1.一对一

  • 一个信号连接一个槽

  • 一个信号连接另一个信号

2.一对多

  • 一个信号连接多个槽

3.多对一

  • 多个信号连接一个槽函数

3.信号和槽的其他说明

1.信号与槽的断开

  • 使用disconnect()即可断开连接,用法和connect()基本一致
  • 说明 :
    • 大部分情况下,把信号和槽连上之后,就不必关了
    • 主动断开往往是为了把信号重新绑定到另一个槽函数上

2.使用Lambda表达式定义槽函数

  • 早期版本的Qt,若要使⽤Lambda表达式 ,要在".pro"⽂件中添加: CONFIG += C++11

  • Qt5以上的版本⽆需⼿动添加,在新建项⽬时会⾃动添加

  • 示例 :正常使用

    cpp 复制代码
    connect(btn, &QPushButton::clicked, this, [=](){
    	this->close();
    });
  • 特别示例 :当"connect()"第三个参数为"this"时,第四个参数使⽤Lambda表达式时,可以省略掉第三个参数的this

    cpp 复制代码
    connect(btn, &QPushButton::clicked, [=](){
    	this->close();
    });

3.信号与槽的优缺点

  • 优点:松散耦合
    • Qt的信号槽机制保证了信号与槽函数的调⽤
      • 信号发送者不需要知道发出的信号被哪个对象的槽函数接收
      • 槽函数也不需要知道哪些信号关联了⾃⼰,
    • ⽀持信号槽机制的类或者⽗类必须继承于QObject类
  • 缺点:效率较低
    • 与回调函数相⽐,信号和槽稍微慢⼀些,因为它们提供了更⾼的灵活性,尽管在实际应⽤程序中差别不⼤
    • 通过信号调⽤的槽函数⽐直接调⽤的速度慢约10倍 ,这是定位信号的接收对象所需的开销
      • 遍历所有关联
      • 编组/解组传递的参数
      • 多线程时,信号可能需要排队
    • 这种调⽤速度对性能要求不是⾮常⾼的场景是可以忽略的,是可以满⾜绝⼤部分场景
    • ⼀个客⼾端程序中,最慢的环节往往是"⼈"
      • 假设本⾝基于回调的⽅式是10us,使⽤信号槽的⽅式是100us,对于使⽤程序的⼈来说,是感知不到的
相关推荐
码客-ygluu26 分钟前
X3 LUA 异步分布式微服务集群框架
c++·架构·lua
九英里路3 小时前
protobuf快速上手
网络·c++·中间件·json·谷歌·序列化·protobuf
纪念 2294 小时前
C++ 算法基础 (差分)
开发语言·c++·算法
ShineWinsu9 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
落羽的落羽9 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
汉克老师15 小时前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++
晴天的雨.99216 小时前
【C++】继承篇
java·开发语言·c++
青少儿编程课堂16 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
another heaven16 小时前
【C/C++ 第一次跨越(上):用 C++11/14 停止制造新的旧代码】
c语言·c++·制造
qq_4069810316 小时前
c++ lamda(三)Lambda表达式
java·前端·c++