文章目录

  • 1 多线程与界面组件的通信
    • 1.1 通过信号与槽实现多线程与界面组件的通信
    • 1.2 通过自定义事件实现多线程与界面组件的通信

1 多线程与界面组件的通信

有趣的问题:

  • 是否可以在子线程中创建界面组件?

如上代码运行程序会直接崩溃!

GUI系统设计原则:

  • 所有界面组件的操作都只能在主线程中完成;因此,主线程也叫做UI线程!

思考:

  • 子线程如何对界面组件进行更新?

可以通过信号与槽或者事件进行更新!

1.1 通过信号与槽实现多线程与界面组件的通信

解决方案:信号与槽

  1. 在子线程类中定义界面组件的更新信号(updateUI)。
  2. 在主窗口类中定义更新界面组件的槽函数(setInfo)。
  3. 使用异步方式连接更新信号到槽函数(updateUI->setInfo):
    • 子线程通过发射信号的方式更新界面组件。
    • 所有的界面组件对象只能依附于主线程。


UpdateThread.h:

#ifndef UPDATETHREAD_H
#define UPDATETHREAD_H#include <QThread>class UpdateThread : public QThread
{Q_OBJECTprotected:void run();
public:explicit UpdateThread(QObject *parent = 0);signals:void updateUI(QString text);};#endif // UPDATETHREAD_H

UpdateThread.cpp:

#include "UpdateThread.h"UpdateThread::UpdateThread(QObject *parent) :QThread(parent)
{}void UpdateThread::run()
{emit updateUI("Begin");for(int i=0; i<10; i++){emit updateUI(QString::number(i));sleep(1);}emit updateUI("End");
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include <QPlainTextEdit>
#include "UpdateThread.h"class Widget : public QWidget
{Q_OBJECTUpdateThread m_thread;QPlainTextEdit textEdit;
protected slots:void appendText(QString text);
public:Widget(QWidget *parent = 0);~Widget();
};#endif // WIDGET_H

Widget.cpp:

#include "Widget.h"
#include "TestThread.h"Widget::Widget(QWidget *parent): QWidget(parent)
{// TestThread* ptt = new TestThread();// ptt->start();textEdit.setParent(this);textEdit.move(20, 20);textEdit.resize(200, 150);textEdit.setReadOnly(true);connect(&m_thread, SIGNAL(updateUI(QString)), this, SLOT(appendText(QString)));m_thread.start();
}void Widget::appendText(QString text)
{textEdit.appendPlainText(text);
}Widget::~Widget()
{}

main.cpp:

#include <QtGui/QApplication>
#include "Widget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

思考:

  • 子线程能够更改界面组件状态的本质是什么?

    总结一下:
  • 现代GUI平台只允许在主线程中直接操作界面组件。
  • Qt中可以借助信号与槽的机制在子线程中操作界面组件。
  • 进行信号与槽的连接时必须采用异步连接的方式。
  • 界面组件对象必须依附于主线程。

1.2 通过自定义事件实现多线程与界面组件的通信

解决方案-发送自定义事件:

  1. 自定义事件类用于描述界面更新细节。
  2. 在主窗口类中重写事件处理函数event。
  3. 使用postEvent函数(异步方式)发送自定义事件类对象:
    • 子线程指定接受消息的对象为主窗口对象。
    • 在event事件处理函数更新界面状态。


StringEvent.h:

#ifndef _STRINGEVENT_H_
#define _STRINGEVENT_H_#include <QEvent>
#include <QString>class StringEvent : public QEvent
{QString m_data;
public:const static Type TYPE = static_cast<Type>(QEvent::User + 0xFF);explicit StringEvent(QString data = "");QString data();};#endif // _STRINGEVENT_H_

StringEvent.cpp:

#include "StringEvent.h"StringEvent::StringEvent(QString data) : QEvent(TYPE)
{m_data = data;
}QString StringEvent::data()
{return m_data;
}

UpdateThread.h:

#ifndef UPDATETHREAD_H
#define UPDATETHREAD_H#include <QThread>class UpdateThread : public QThread
{Q_OBJECTprotected:void run();
public:explicit UpdateThread(QObject *parent = 0);};#endif // UPDATETHREAD_H

UpdateThread.cpp:

#include "UpdateThread.h"
#include <QApplication>
#include "StringEvent.h"UpdateThread::UpdateThread(QObject *parent) :QThread(parent)
{}void UpdateThread::run()
{// emit updateUI("Begin");QApplication::postEvent(parent(), new StringEvent("Begin"));for(int i=0; i<10; i++){// emit updateUI(QString::number(i));QApplication::postEvent(parent(), new StringEvent(QString::number(i)));sleep(1);}// emit updateUI("End");QApplication::postEvent(parent(), new StringEvent("End"));
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include <QPlainTextEdit>
#include "UpdateThread.h"class Widget : public QWidget
{Q_OBJECTUpdateThread m_thread;QPlainTextEdit textEdit;public:Widget(QWidget *parent = 0);bool event(QEvent *evt);~Widget();
};#endif // WIDGET_H

Widget.cpp:

#include "Widget.h"
#include "StringEvent.h"Widget::Widget(QWidget *parent): QWidget(parent)
{textEdit.setParent(this);textEdit.move(20, 20);textEdit.resize(200, 150);textEdit.setReadOnly(true);m_thread.setParent(this);m_thread.start();
}bool Widget::event(QEvent *evt)
{bool ret = true;if( evt->type() == StringEvent::TYPE ){StringEvent* se = dynamic_cast<StringEvent*>(evt);if( se != NULL ){textEdit.appendPlainText(se->data());}}else{ret = QWidget::event(evt);}return ret;
}Widget::~Widget()
{}

main.cpp:

#include <QtGui/QApplication>
#include "Widget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

总结一下:

  • Qt中可以发送自定义事件在子线程中操作界面组件。
  • 必须使用postEvent函数进行事件发送(异步方式)。
  • 发送的事件对象必须在堆上创建。
  • 子线程创建时必须附带目标对象的地址信息。

参考资料:

  1. QT实验分析教程

Qt中多线程与界面组件的通信相关推荐

  1. QT 中多线程实现方法总结

    第一: 用QtConcurrentRun类,适合在另一个线程中运行一个函数.不用继承类,很方便 第二:用QRunnable和QThreadPool结合.继承QRunnable,重写run函数,然后用Q ...

  2. Qt中多线程间的同步

    文章目录 1 Qt中多线程间的同步 1 Qt中多线程间的同步 多线程编程的本质是什么? 并发性是多线程编程的本质. 在宏观上,所有线程并行执行. 多个线程间相互独立,互补干涉. 常规解决方案设计: 问 ...

  3. c#,c++,qt中多线程访问UI控件线程的问题汇总

    c#和MFC中可以创建UI控件及模态/非模态对话框,Qt中只能在主UI线程中创建访问UI控件. c#和MFC中可以通过全局变量或指针句柄等方式在工作线程中访问其他UI线程控件,其中c#需要Invoke ...

  4. Qt中使用QUdpSocket类实现UDP通信

    UDP 通信介绍 UDP(User Datagram Protocol,用户数据报协议) UDP是一个轻量级.不可靠.面向数据报的.无连接的传输层协议,多用于可靠性要求不严格,不是非常重要的传输,如直 ...

  5. Qt中多线程间的互斥

    文章目录 1 多线程间的互斥 1.1 生产消费者问题 1.2 QMutex 1.3 死锁问题 1.4 信号量 1 多线程间的互斥 值得思考的问题: 多个线程间除了在时序上可能产生依赖,在其它方面是否也 ...

  6. Qt中多线程moveToThread

    Qt中实现多线程的方式.1.利用继承QThread类,重写run函数实习.2.将对象使用moveToThread方法,利用信号槽实现.3.利用QtConcurrent相关QFuture实现. 以前一直 ...

  7. Qt中多线程的一种使用

    系统需要在子窗体中进行一个耗时的数据融合过程,之前意识到UI所在的主线程会被卡死的情况,但因为赶进度需要扩展新功能就暂时没顾上,只用了一种相对妥协的方法,QProgressDialog用于进度的显示, ...

  8. Qt、C++小票打印----端口(com)、并口(lpt)----并介绍了qt中qwebview的使用及js通信

    记录一下自己做过的东西,希望对大家可以有帮助. 一.介绍 端口和并口打印,都是读写设备的操作,类似于linux中一切设备皆文件的 赶脚. (1)  利用纯qt实现端口读写,有一个相关的类库可以使用,事 ...

  9. Qt中的QWidget

    文章目录 1 窗口组件 2 QWidget类 3 窗口类型 4 窗口部件的大小设置 5 QWidget常用方法 1 窗口组件 Qt中的窗口组件: 图形用户界面由不同的窗口和窗口组件构成. <Qt ...

最新文章

  1. Android进阶笔记:Messenger源码详解
  2. jmeter web监听结果_JMeter 性能测试基本过程及示例
  3. AndroidDialog
  4. matlab 基于Topsis的熵权法2
  5. linux 文件大小_linux系统中查看目录大小的du命令常
  6. 40. Combination Sum II **
  7. 为什么敏捷开发在亚洲实行不了
  8. idea中Terminal终端无法执行GIT命令
  9. linux自动挂载ntfs分区,Ubuntu 12.04 开机自动挂载ntfs分区
  10. 中国开杯闪点测试仪行业市场供需与战略研究报告
  11. vmware虚拟机i copied it 和 i moved it的区别
  12. Linux系统优化之网络IO调优
  13. 从0开始学习C#第二天
  14. 南京大学计算机专业推免生,南大计算机系招收2014级研究生外校推免生复试名单...
  15. USB Repair v8.1.3.1285 – USB 修复工具
  16. Java 与或非 判断
  17. 海康8800实时视频Android客户端集成总结
  18. 一个程序员近20年工资单
  19. html树状图在线画板,五款在线思维导图工具,总有一款适合你
  20. MOSFET开通特性(2)——动态特性

热门文章

  1. 3.4 归一化网络的激活函数-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  2. 数字电路可控门电路原理(三态/同相/反相、缓冲/驱动电路)
  3. 【工具】云文档办公利器!腾讯文档好评!
  4. 【网上的都不靠谱?还是得改源码】用Javasisst的字节码插桩技术,彻底解决Gson转Map时,Int变成double问题...
  5. MySQL用户管理、常用SQL语句、MySQL数据库备份恢复
  6. Django使用心得(二)
  7. extract-text-webpack-plugin 的使用及安装
  8. 顶级程序员的10条最佳实践
  9. Oracle数据表和Constraint管理
  10. 售前常见问题解答(一)