Qt中多线程与界面组件的通信
生活随笔
收集整理的這篇文章主要介紹了
Qt中多线程与界面组件的通信
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1 多線程與界面組件的通信
- 1.1 通過信號與槽實現多線程與界面組件的通信
- 1.2 通過自定義事件實現多線程與界面組件的通信
1 多線程與界面組件的通信
有趣的問題:
- 是否可以在子線程中創建界面組件?
如上代碼運行程序會直接崩潰!
GUI系統設計原則:
- 所有界面組件的操作都只能在主線程中完成;因此,主線程也叫做UI線程!
思考:
- 子線程如何對界面組件進行更新?
可以通過信號與槽或者事件進行更新!
1.1 通過信號與槽實現多線程與界面組件的通信
解決方案:信號與槽
- 子線程通過發射信號的方式更新界面組件。
- 所有的界面組件對象只能依附于主線程。
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_HWidget.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事件處理函數更新界面狀態。
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_HUpdateThread.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_HWidget.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中多线程与界面组件的通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代码结构分层
- 下一篇: 用信号量实现任务间单向同步