connect

connect用于连接信号和槽函数,但是我们经常忽略最后一个参数,本人在写代码时遇到了bug,选择一个符号进行多次标绘,再选择其他符号时,会将上一次选择的符号也进行标绘,主要时connect最后一个参数搞的鬼。

当conncet最后一个参数不写时,connect多少次,槽函数就执行多少次,本人遇到的bug需要将最后一个参数设为Qt::UniqueConnection,避免多次连接,只连接一次。

Qt::AutoConnection: 自动。一般不写就默认是这个,使用这个值会根据实际情况去判断,如果sender和receiver在同一个线程,则自动使用Qt::DirectConnection,如果不在一个线程,则自动使用Qt::QueuedConnection。
Qt::DirectConnection:直连。槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃。
Qt::QueuedConnection:队列连接。槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个。
Qt::BlockingQueuedConnection:阻塞队列连接。槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
Qt::UniqueConnection:唯一连接。这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接。

diconnect

disconnect(myObject, nullptr, nullptr, nullptr)等同于myObject->disconnect();, 断开myObject的所有信号与任何槽的关联;
disconnect(myObject, SIGNAL(mySignal()), nullptr, nullptr) 等同于myObject>disconnect(SIGNAL(mySignal()));断开myObject得mySignal信号与任何槽的关联;
disconnect(myObject, nullptr, myReceiver, nullptr);等同于myObject->disconnect(myReceiver);断开信号发送者myObject和信号接收者myReceiver之间的关联;
QObject::disconnect(lineEdit, &QLineEdit::textChanged, label, &QLabel::setText);断开特定信号发送者和接收者之间的关联

其中conncet必须与disconnect成对出现,不然,disconncet之后就连接不上信号

信号槽实现原理

1、信号与槽的实现是借助了Qt 的元对象系统,元对象系统有一个元对象编译器,程序编译之前会有一个预处理过程,预处理将一个类/对象中的信号,槽的字符串值分别保存在一个容器中,可能是字符串或者其他的有序容器。

2、现在有两个容器,比如string_sig,保存了所有的信号的字符串值;string_slot保存了所有的槽函数的字符窜值。

3、每次调用connect()函数建立信号与槽的连接,就是将给定信号与给定的接收方及其槽函数存储在发送方对象的映射容器中,比如multimap,建立起信号与槽的一一对应关系。

4、发射信号其实就是调用信号函数(信号就是一种函数),根据该信号的索引在multimap中找到对应的槽函数,在调用槽函数即可。

5、信号与槽的本质就是函数的调用。

例子:

#include <map>
#include<iostream>
# define slot
# define siginal protected
# define emit
using namespace std;
class Object;struct MetaObject//元对象 每个Object有一个,保存自己拥有的信号和槽函数
{const char* sig_names;const char* slts_names;static void active(Object* sender, int idx);
};struct Connection//保存接收方及其序号
{Object* receiver;int method;
};typedef std::multimap<int, Connection> ConnectionMap;
//<信号,接收方>每个Object有一个,保存自己的信号发出时需要通知的接收方。每个信号的接收方可能不止一个,用multimap
typedef std::multimap<int, Connection>::iterator ConnectionMapIt;static int find_string(const char* str, const char* substr)
{if (strlen(str) < strlen(substr))return -1;int idx = 0;int len = strlen(substr);bool start = true;const char* pos = str;while (*pos){if (start && !strncmp(pos, substr, len) && pos[len] == '\n')return idx;start = false;if (*pos == '\n'){idx++;start = true;}pos++;}return -1;
}class Object
{friend class MetaObject;
public:Object() {};virtual ~Object() {};static void connect(Object* sender, const char* sig, Object* receiver, const char* slt);void testSignal() { emit sig1(); }//测试函数siginal:void sig1() //信号{cout << "信号发出" << endl;MetaObject::active(this, 0);}public slot:void slot1() { cout << "槽函数执行" << endl; }//槽函数private:static MetaObject meta;//保存自己拥有的信号和槽函数ConnectionMap connections;//multimap<int, Connection>,void metacall(int idx);//根据key去查询对应的槽函数
};static const char sig_names[] = "sig1\n";//保存对象中所有信号的字符串的容器
static const char slts_names[] = "slot1\n";//保存对象中所有槽函数字符串的容器
MetaObject Object::meta = { sig_names, slts_names };//初始化元对象void Object::metacall(int idx)//根据key去查询对应的槽函数
{switch (idx){case 0:slot1();break;default:break;};
}void Object::connect(Object* sender, const char* sig, Object* receiver, const char* slt)//静态成员函数  connect建立信号与槽的连接
{int sig_idx = find_string(sender->meta.sig_names, sig);//查询有没有这个信号和槽函数int slt_idx = find_string(receiver->meta.slts_names, slt);if (sig_idx == -1 || slt_idx == -1){perror("signal or slot not found!");}else //添加{Connection c = { receiver, slt_idx };//保存接收方及其槽函数idsender->connections.insert(std::pair<int, Connection>(sig_idx, c));//发送方保存接收方信息}
}void MetaObject::active(Object* sender, int idx)//信号发出,根据发出者找出它的接收方
{ConnectionMapIt it;std::pair<ConnectionMapIt, ConnectionMapIt> ret;ret = sender->connections.equal_range(idx);//equal_range主要是找在multimap中的key相等的value,也是一个迭代器for (it = ret.first; it != ret.second; ++it){Connection c = (*it).second;//获取之前保存的接受方消息c.receiver->metacall(c.method);//接收方执行之前绑定的槽函数}
}int main()
{Object obj1, obj2;Object::connect(&obj1, "sig1", &obj2, "slot1");//连接信号obj1.testSignal();system("pause");return 0;
}

QT中connect、disconnect和信号槽实现原理相关推荐

  1. 最新QT从入门到实战完整版(08.qt中的坐标系-09 信号和槽-点击按钮关闭窗口_)

    最新QT从入门到实战完整版(08.qt中的坐标系-09 信号和槽-点击按钮关闭窗口_) 一.08.qt中的坐标系 二,09 信号和槽-点击按钮关闭窗口_ 来自 一.08.qt中的坐标系 二,09 信号 ...

  2. Qt计算器开发(二):信号槽实现数学表达式合法性检查

    表达式的合法性 由于我们的计算器不是单步计算的,所以我们能够一次性输入一个长表达式.然而假设用户输入的长表达式不合法的话,那么就会引发灾难.所以有必要对于用户的输入做一个限制. 一些限制举例: 比方, ...

  3. 1.QT元对象系统、信号槽概述、宏Q_OBJECT

    一.元对象系统(Meta-Object System) Qt添加C++原本不具备的元对象系统,元对象系统提供了信号槽机制,运行时类型信息和动态属性系统. 元对象系统基于三点: 1.元对象系统为以QOb ...

  4. 【Qt】Connect/Disconnect

    关注connect/disconnect的返回值 在创建connect时,一定注意位置,确保只创建一次,否则变量没释放,又connect了,emit之后,会多次进入槽函数. 原则上不需要调用disco ...

  5. QT中connect函数的几种用法详解总结

    前言 信号与槽机制是QT非常核心的东西,通过信号与槽我们可以将不同的部分有机的结合起来,使得各个组件之间的交互简单高效,信号与曹槽像是设计模式中的观察者模式(我自己觉得是这样),只关心信号何时发来,以 ...

  6. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.6 自定义信号槽

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1gA4y1d7gz 上节课,我们讲解了标准信号槽,标准信号槽中,信号和槽函数,都是 Qt 框架定 ...

  7. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.5 标准信号槽

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1vW4y1676Q 本节讲解信号和槽的概念,以及标准的信号槽 1. 什么是信号槽 1.1 信号 ...

  8. Qt积少成多,QComboBox自定义信号槽

    阶段总结,QComboBox的信号槽连接: 1.默认名称 void on_cmbItemList_currentIndexChanged(const QString &text); 2.指定槽 ...

  9. Qt中的四种信号与槽的连接方式

    1. UI界面右键点击控件,选择"转到槽",系统会在cpp中自动添加这个组件对应的槽函数 2.在Ui界面的下面 siga如l & slot editor栏中手动添加 3.在 ...

最新文章

  1. iPhone App开发导航条(Navigation Bar)素材PSD下载
  2. 为什么有人会觉得灵魂无处安放
  3. 关于 Kubernetes 规划的灵魂 n 问
  4. dubbo使用遇到的问题
  5. JAVA程序设计----集合基础之Map
  6. JS 对象(Object)和字符串(String)互转
  7. linux家庭云服务器,linux服务器云(linux家用云服务器)
  8. 源码解读_入口开始解读Vue源码系列(二)——new Vue 的故事
  9. 固定频率调用接口方案
  10. leetcode之旋转链表
  11. JSP入门:什么是JSP和Servlet?
  12. flv怎么转换成html5,怎么转asf格式 如何将flv格式转换成asf格式?
  13. 【贵州大学计算机考研1】三本学生考研上岸贵州大学软件工程专硕(附带真题与答案)
  14. ZIGBEE 工程内区分终端与协调器
  15. 2020最新Ubutu18.04安装NVIDIA出现如下报错解决方法[亲测可用]
  16. 20145236 《Java程序设计》第4周学习总结
  17. java happen-before_Java内存模型happen-before的实现原理
  18. [容斥 状压DP] Atcoder ARC093 F - Dark Horse
  19. 触摸屏键盘插件Virtual Keyboard 该怎么用 Virtual Keyboard 入门指南
  20. 孙溟㠭先生书画艺术《贵妃》

热门文章

  1. idea快捷键,你要是不看就可惜了
  2. 【JavaScript】ESModule(esm)
  3. 快速解决Win 7升级后无法正常进入睡眠模式的问题——386w.com
  4. 金钩钓鱼java代码_金钩钓鱼
  5. SQLYog 数据连接配置的迁移
  6. 一维谐振子定态 Schrödinger 方程的数值解法
  7. 中科院计算所培训中心--2019年三季度课程新鲜出炉啦!
  8. Matlab之化简多项式
  9. [译] 使用 Espresso 隔离测试视图
  10. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A - Wasserstein Distance