Qt中多线程与界面组件的通信
文章目录
- 1 多线程与界面组件的通信
- 1.1 通过信号与槽实现多线程与界面组件的通信
- 1.2 通过自定义事件实现多线程与界面组件的通信
1 多线程与界面组件的通信
有趣的问题:
- 是否可以在子线程中创建界面组件?
如上代码运行程序会直接崩溃!
GUI系统设计原则:
- 所有界面组件的操作都只能在主线程中完成;因此,主线程也叫做UI线程!
思考:
- 子线程如何对界面组件进行更新?
可以通过信号与槽或者事件进行更新!
1.1 通过信号与槽实现多线程与界面组件的通信
解决方案:信号与槽
- 在子线程类中定义界面组件的更新信号(updateUI)。
- 在主窗口类中定义更新界面组件的槽函数(setInfo)。
- 使用异步方式连接更新信号到槽函数(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 通过自定义事件实现多线程与界面组件的通信
解决方案-发送自定义事件:
- 自定义事件类用于描述界面更新细节。
- 在主窗口类中重写事件处理函数event。
- 使用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函数进行事件发送(异步方式)。
- 发送的事件对象必须在堆上创建。
- 子线程创建时必须附带目标对象的地址信息。
参考资料:
- QT实验分析教程
Qt中多线程与界面组件的通信相关推荐
- QT 中多线程实现方法总结
第一: 用QtConcurrentRun类,适合在另一个线程中运行一个函数.不用继承类,很方便 第二:用QRunnable和QThreadPool结合.继承QRunnable,重写run函数,然后用Q ...
- Qt中多线程间的同步
文章目录 1 Qt中多线程间的同步 1 Qt中多线程间的同步 多线程编程的本质是什么? 并发性是多线程编程的本质. 在宏观上,所有线程并行执行. 多个线程间相互独立,互补干涉. 常规解决方案设计: 问 ...
- c#,c++,qt中多线程访问UI控件线程的问题汇总
c#和MFC中可以创建UI控件及模态/非模态对话框,Qt中只能在主UI线程中创建访问UI控件. c#和MFC中可以通过全局变量或指针句柄等方式在工作线程中访问其他UI线程控件,其中c#需要Invoke ...
- Qt中使用QUdpSocket类实现UDP通信
UDP 通信介绍 UDP(User Datagram Protocol,用户数据报协议) UDP是一个轻量级.不可靠.面向数据报的.无连接的传输层协议,多用于可靠性要求不严格,不是非常重要的传输,如直 ...
- Qt中多线程间的互斥
文章目录 1 多线程间的互斥 1.1 生产消费者问题 1.2 QMutex 1.3 死锁问题 1.4 信号量 1 多线程间的互斥 值得思考的问题: 多个线程间除了在时序上可能产生依赖,在其它方面是否也 ...
- Qt中多线程moveToThread
Qt中实现多线程的方式.1.利用继承QThread类,重写run函数实习.2.将对象使用moveToThread方法,利用信号槽实现.3.利用QtConcurrent相关QFuture实现. 以前一直 ...
- Qt中多线程的一种使用
系统需要在子窗体中进行一个耗时的数据融合过程,之前意识到UI所在的主线程会被卡死的情况,但因为赶进度需要扩展新功能就暂时没顾上,只用了一种相对妥协的方法,QProgressDialog用于进度的显示, ...
- Qt、C++小票打印----端口(com)、并口(lpt)----并介绍了qt中qwebview的使用及js通信
记录一下自己做过的东西,希望对大家可以有帮助. 一.介绍 端口和并口打印,都是读写设备的操作,类似于linux中一切设备皆文件的 赶脚. (1) 利用纯qt实现端口读写,有一个相关的类库可以使用,事 ...
- Qt中的QWidget
文章目录 1 窗口组件 2 QWidget类 3 窗口类型 4 窗口部件的大小设置 5 QWidget常用方法 1 窗口组件 Qt中的窗口组件: 图形用户界面由不同的窗口和窗口组件构成. <Qt ...
最新文章
- Android进阶笔记:Messenger源码详解
- jmeter web监听结果_JMeter 性能测试基本过程及示例
- AndroidDialog
- matlab 基于Topsis的熵权法2
- linux 文件大小_linux系统中查看目录大小的du命令常
- 40. Combination Sum II **
- 为什么敏捷开发在亚洲实行不了
- idea中Terminal终端无法执行GIT命令
- linux自动挂载ntfs分区,Ubuntu 12.04 开机自动挂载ntfs分区
- 中国开杯闪点测试仪行业市场供需与战略研究报告
- vmware虚拟机i copied it 和 i moved it的区别
- Linux系统优化之网络IO调优
- 从0开始学习C#第二天
- 南京大学计算机专业推免生,南大计算机系招收2014级研究生外校推免生复试名单...
- USB Repair v8.1.3.1285 – USB 修复工具
- Java 与或非 判断
- 海康8800实时视频Android客户端集成总结
- 一个程序员近20年工资单
- html树状图在线画板,五款在线思维导图工具,总有一款适合你
- MOSFET开通特性(2)——动态特性
热门文章
- 3.4 归一化网络的激活函数-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
- 数字电路可控门电路原理(三态/同相/反相、缓冲/驱动电路)
- 【工具】云文档办公利器!腾讯文档好评!
- 【网上的都不靠谱?还是得改源码】用Javasisst的字节码插桩技术,彻底解决Gson转Map时,Int变成double问题...
- MySQL用户管理、常用SQL语句、MySQL数据库备份恢复
- Django使用心得(二)
- extract-text-webpack-plugin 的使用及安装
- 顶级程序员的10条最佳实践
- Oracle数据表和Constraint管理
- 售前常见问题解答(一)