日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt中多线程与界面组件的通信

發(fā)布時間:2025/4/5 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt中多线程与界面组件的通信 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1 多線程與界面組件的通信
      • 1.1 通過信號與槽實現多線程與界面組件的通信
      • 1.2 通過自定義事件實現多線程與界面組件的通信

1 多線程與界面組件的通信

有趣的問題:

  • 是否可以在子線程中創(chuàng)建界面組件?

如上代碼運行程序會直接崩潰!

GUI系統設計原則:

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

思考:

  • 子線程如何對界面組件進行更新?

可以通過信號與槽或者事件進行更新!

1.1 通過信號與槽實現多線程與界面組件的通信

解決方案:信號與槽

  • 在子線程類中定義界面組件的更新信號(updateUI)。
  • 在主窗口類中定義更新界面組件的槽函數(setInfo)。
  • 使用異步方式連接更新信號到槽函數(updateUI->setInfo):
    • 子線程通過發(fā)射信號的方式更新界面組件。
    • 所有的界面組件對象只能依附于主線程。

  • 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(); }

    思考:

    • 子線程能夠更改界面組件狀態(tài)的本質是什么?

      總結一下:
    • 現代GUI平臺只允許在主線程中直接操作界面組件。
    • Qt中可以借助信號與槽的機制在子線程中操作界面組件。
    • 進行信號與槽的連接時必須采用異步連接的方式。
    • 界面組件對象必須依附于主線程。

    1.2 通過自定義事件實現多線程與界面組件的通信

    解決方案-發(fā)送自定義事件:

  • 自定義事件類用于描述界面更新細節(jié)。
  • 在主窗口類中重寫事件處理函數event。
  • 使用postEvent函數(異步方式)發(fā)送自定義事件類對象:
    • 子線程指定接受消息的對象為主窗口對象。
    • 在event事件處理函數更新界面狀態(tài)。

  • 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中可以發(fā)送自定義事件在子線程中操作界面組件。
    • 必須使用postEvent函數進行事件發(fā)送(異步方式)。
    • 發(fā)送的事件對象必須在堆上創(chuàng)建。
    • 子線程創(chuàng)建時必須附帶目標對象的地址信息。

    參考資料:

  • QT實驗分析教程
  • 總結

    以上是生活随笔為你收集整理的Qt中多线程与界面组件的通信的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。