关于QT的线程通信,我们都会想到signal & slot机制。先回顾下利用signal & slot机制实现控件消息处理的方法。

控件消息处理

假设我们的主界面上有一个使用ui->btn指向的QPushButton对象,要实现该对象的clicked消息处理,可以在主界面对象MainWindow上添加一个slot方法onBtnClicked,并在其构造函数中使用connect方法与ui->btn的clicked消息进行绑定,如下:

MainWindow::MainWindow(QWidget* parent) :QMainWindow(parent), ui(new ui::MainWindow)
{ui->setupUi(this);// 方法一,推荐使用connect(ui->btn, &QPushButton::clicked,        this, &MainWindow::onBtnClicked);// 方法二//connect(ui->btn, SIGNAL(clicked),          this, SLOT(onBtnClicked));…
}

void MainWindow::onBtnClicked(void){  doSomething();}

事实上这种方法很繁杂。单纯为了处理一个按钮的消息我们就要新建一个slot方法,当界面控件多了的时候,会使得代码臃肿不堪(即使你可以设计成多个控件消息共享一个槽函数)。

在新版的支持C++11的QT中,我们可以使用Lambda函数优雅地解决这个问题。如下:

MainWindow::MainWindow(QWidget* parent) :QMainWindow(parent), ui(new ui::MainWindow)
{setupUi(this);// 使用lambda函数实现slot方法connect(ui->btn, &QPushButton::clicked, [&](){doSomething();});…
}

使用Lambda函数的另一个好处是,可以借助闭包的概念加速开发。比如我曾做过一个运动控制项目,界面上有32个之多的QCheckBox控件,如下:

需要响应每个QCheckBox控件的clicked消息,改变对应的IO口电平输出。我的做法是,对这些控件进行Tab排序,并将第一个控件命名为ui->ioChk,然后编码如下:

typedef QCheckBox   *F_QCB;
#define F_QNEXT(w)  (w->nextInFocusChain())

…

MainWindow::MainWindow(QWidget* parent) :  QMainWindow(parent), ui(new ui::MainWindow){  setupUi(ui);    …  F_QCB cb = ui->ioChk;  for (int i = 0; i < 32; ++i)  {    connect(cb, &QCheckBox::clicked, [=](bool s){      setIo(i, s);  // 改变第i个端口的输出电平为s    });    cb = F_QNEXT(cb);  }  …}

要读懂上面的程序,你需要一些关于C++11标准的Lambda函数的知识,代码中使用值捕获方式捕获i变量值形成闭包函数,这些闭包函数被绑定到不同的QCheckBox的clicked消息中。

线程间通信

很长的时间里,我都以为QT的signal & slot机制只适用于单向异步通信。事实上,它可以设计为带返回的同步通信。

有个案例如下:工作线程在运行时需要同步提取界面上的参数信息(假设要提取界面上的QSpinBox的值),要同时保证界面的响应和工作线程的不间断运转。

一种可能的实现方法是,在工作线程上的某个对象定义一个request消息,绑定到MainWindow的response槽中,然后在MainWindow中定义一个answer消息,绑定到工作线程上的某个对象的onAnswer槽中。通信过程如下:

1. 工作线程需要界面参数值,发送request消息

2. 主线程接收到request消息,开始执行response槽方法

3. 在response函数中,获取界面控件的值,发送answer消息

4. 工作线程收到answer消息,调用onAnswer槽方法,恢复之前的运行流程

这种方法条理清晰,但编码实现过于繁琐。我的实现方法是,在工作线程实现一个形如request(QString req, QVariant& arg)的消息,然后以QT::BlockBlockingQueuedConnection方式连接至MainWindow的response槽方法中。编码如下:

WorkerThread声明:

#ifndef __WORKER_THREAD_H#define __WORKER_THREAD_H

class WorkerThread : public QThread {public:  …  // @Override  void run();

private:  // 用于通信  class InThreadObject;  InThreadObject *ito;  …}

#endif

WorkerThread实现:

class WorkerThread::InThreadObject : public QObject {  Q_OBJECT

signals:  void request(QString req, QVariant& arg);}

void WorkerThread::run(){  ito = new InThreadObject;  …  // 注意下面的连接使用了QT::BlockingQueuedConnection选项  connect(ito,       &InThreadObject::request,       pMainWindow,       &MainWindow::response,       QT::BlockingQueuedConnection);  …  // 同步获取界面参数值  QVariant var;  ito->request("param.level", var);  // 这里会同步等待主线程执行response函数完  int param = var.toInt();  ……}

MainWindow相关实现:

void MainWindow::response(QString req, QVariant& ans){  if (req == "param.level")  {    // 获取控件值并存放至ans引用变量中    ans.setValue(ui->levelSpin->value());  }}

本次经验分享完毕,关于一些具体的技术细节,如QT的消息与槽机制、C++11的Lambda函数还请读者另行学习。

本文链接:http://www.cnblogs.com/wenris/p/4447481.html。

QT高级编程技巧(一)-- 编写高效的signal slot通信代码相关推荐

  1. C++高级编程篇-如何编写高效的C++篇

    为了编写高效的程序,需要在设计层次上做考虑,并在实现层次上考虑细节.(一定要在程序的生命周期已开始就考虑性能). "编写高效的C++程序"指要编写能高效运行的程序,而不是高效地编写 ...

  2. Qt高级编程之多线程处理

    目录 前言 一.简介 1.1 并发执行机制 1.2 多线程机制 1.3 多线程处理的方式 二.Qt高级线程类实现多线程 2.1 在线程中执行函数 2.1.1 使用QtConcurrent::run() ...

  3. python高级应用_Python高级编程技巧

    Python 高级编程技巧 本文展示一些高级的 Python 设计结构和它们的使用方法.在日常工作中,你可以根据需要 选择合适的数据结构, 例如对快速查找性的要求. 对数据一致性的要求或是对索引的要求 ...

  4. qt android 网络编程实例,QT网络编程Tcp下C/S架构的即时通信实例

    先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面. #ifndef TCPCLIENT_H #define TCPCLIENT_H #include #include #include # ...

  5. python function at 0x00000_python高级编程技巧 - BugError

    由python高级编程处学习 Python 列表解析语法 [] 和生成 器 () 语法类似 [expr for iter_var in iterable] 或 [expr for iter_var i ...

  6. java主类与源代码名称_Java高级编程基础:类文件结构解析,看穿Class代码背后的秘密...

    类文件结构 在说完了JVM内部结构后,接下来我们需要说一下另外一个非常重要的基础概念Class类结构. 我们既然知道了开发的Java源代码会首先被编译成字节码文件保存,JVM的类加载器会读取这些文件内 ...

  7. QT高级编程之基本函数用法

    1.QString类函数介绍 toInt()函数,可以将整型按照不同进制转换为QString对象: number()函数,可以将QString对象转换为不同进制的数字: 2.文档查询方法:通过Qt C ...

  8. python 高级编程 豆瓣_python 的一些高级编程技巧

    正文: 本文展示一些高级的Python设计结构和它们的使用方法.在日常工作中,你可以根据需要选择合适的数据结构,例如对快速查找性的要求.对数据一致性的要求或是对索引的要求等,同时也可以将各种数据结构合 ...

  9. Qt-------->第六天,Qt高级编程

    1 IO 进程 线程 IO------->Qt第五天笔记     QFile file("1.txt");file.open();file.read();file.write ...

  10. python高级编程技巧

    个人博客点这里 如何在列表,字典,集合中根据条件筛选数据 方法1:通过迭代来进行判断筛选 解决方案 函数式编程: 如何统计序列中元素的出现频度 解决方案:使用collections.Counter对象 ...

最新文章

  1. 条件分支结构c语言,决定分支的条件一般是什么表达?
  2. 二分类卷积核极限数量实验
  3. distributed representations的意义
  4. k8s minikube管理镜像相关命令:minikube image list/pull/load
  5. .net MVC路由
  6. 第一次更名为OpenInfra的“她”,给我们带来了哪些惊喜?| 技术头条
  7. java计算两列数据差_DAX计算列基于其他表中的两列
  8. 开源的代理服务器HAProxy 易遭严重的 HTTP 请求走私攻击
  9. android studio 混淆方法
  10. navicat如何创建视图
  11. 【Unity】关于ScreenCapture.CaptureScreenshot截屏的尝试
  12. 开发者拒绝写技术博客的常见理由
  13. 代表JAVA线程优先级的常量是_Java 线程优先级
  14. 台式计算机用什么电源线,电脑电源线有什么规格
  15. 13个测试网站访问速度的服务网站
  16. Neutron IPAM源码分析
  17. 如何成为很厉害的程序员?- 读《精进》
  18. 用switch语句根据消费金额计算折扣 (Java经典编程案例)
  19. 讯飞智能录音笔SR702让工作体验更佳
  20. 【数据库与SQL】力扣刷题SQL篇(7)

热门文章

  1. Tableau Online免费注册试用
  2. python 成语库_python正则表达式抓取成语网站
  3. 碾压x雷!分享这款不限速免费下载神器,能在任何操作系统上使用
  4. 图论画图工具 Graph Editor
  5. unity visual effect Graph 1
  6. 深度优先搜索解决迷宫最短路径问题
  7. opengl超级宝典(第5版)的环境搭建
  8. 数据结构算法设计题汇总
  9. 读嵌入式linux驱动程序设计从入门到精通 3
  10. 无责任书评——DOOM启示录 BORLAND传奇