首页 > 代码库 > 第84课 多线程与界面组件的通信(上)
第84课 多线程与界面组件的通信(上)
1. 有趣的问题:
【编程实验】是否可以在子线程中创建界面组件
//TestThread.h
#ifndef TESTTHREAD_H #define TESTTHREAD_H #include <QThread> class TestThread : public QThread { Q_OBJECT protected: void run(); public: explicit TestThread(QObject* parent = 0); }; #endif // TESTTHREAD_H
//TestThread.cpp
#include "TestThread.h" #include <QWidget> TestThread::TestThread(QObject *parent) : QThread(parent) { } void TestThread::run() { QWidget w; //错误!不能在子线程中创建GUI元素 w.show(); exec(); }
//Widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class Widget : public QWidget { Q_OBJECT 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(); } Widget::~Widget() { }
//main.cpp
#include "Widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); } /*出错信息: ASSERT failure in QWidget: "Widgets must be created in the GUI thread." */
2. GUI系统设计原则
(1)所有界面组件的操作都只能在主线程中完成;因此,主线程也叫做UI线程!
(2)子线程通过信号和槽机制通知界面组件进行更新
3. 多线程与界面组件通信的解决方案
(1)在子线程类中定义界面组件更新的信号(如,updateUI)
(2)在主窗口类中定义更新界面组件的槽函数(如,setInfo)
(3)使用异步的队列方式连接更新信号到槽(updateUI→setInfo)
①子线程通过发射信号的方式更新界面组件;
②所有的界面组件对象只能依附于主线程
【编程实验】子线程中更新界面组件
//UpdateThread.h
#ifndef UPDATETHREAD_H #define UPDATETHREAD_H #include <QThread> class UpdateThread : public QThread { Q_OBJECT protected: 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"); //通知UI线程更新 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 <QPlainTextEdit> #include <QWidget> #include "UpdateThread.h" class Widget : public QWidget { Q_OBJECT UpdateThread m_thread; QPlainTextEdit textEdit; protected slots: void appendText(QString text); public: Widget(QWidget *parent = 0); ~Widget(); }; #endif // WIDGET_H
//Widget.cpp
#include "Widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { 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 "Widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
4. 小结
(1)现代GUI平台只允许在主线程中直接操作界面组件
(2)Qt中可以借助信号与槽机制在子线程中操作界面组件
(3)进行信号和槽连接必须采用异步的队列连接方式
(4)界面组件对象只能依附于主线程
第84课 多线程与界面组件的通信(上)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。