Qt线程 工作线程与GUI线程通信
1、信号槽方式
1)在子线程中定义界面组件的更新信号
2)在主窗口类中定义更新界面组件的槽函数
3)使用异步方式连接更新信号到槽函数
子线程通过发送信号的方式更新界面组件,所有的界面组件对象只能依附于GUI线程(主线程)。子线程更新界面状态的本质是子线程发送信号通知主线程界面更新请求,主线程根据具体信号以及信号参数对界面组件进行修改。
代码示例:上一篇线程实现方式二
2、发送自定义事件方式
1)自定义事件用于描述界面更新细节
2)在主窗口类中重写事件处理函数event
3)使用postEvent函数(异步方式)发送自定义事件类对象
子线程指定接收消息的对象为主窗口对象,在event事件处理函数更新界面状态,事件对象在主线程中被处理,event函数在主线程中调用。(注意:发送的事件对象必须在堆空间创建,子线程创建时必须附带目标对象的地址信息)
代码示例:
-
自定义事件类
#ifndef PROGRESSEVENT_H #define PROGRESSEVENT_H #include <QEvent> class ProgressEvent : public QEvent { public: const static Type TYPE = static_cast<Type>(QEvent::User+0xFF); ProgressEvent(int progress = 0):QEvent(TYPE),m_progress(progress){ } int progress() const { return m_progress; } private: int m_progress; }; #endif // PROGRESSEVENT_H
-
工作线程类
#ifndef WORKTHREAD_H #define WORKTHREAD_H #include <QThread> #include <QApplication> #include "progressevent.h" class WorkThread : public QThread { Q_OBJECT public: WorkThread():m_stop(false){ } void run(){ work(); exec(); } void stop(){ m_stop = true; } void work(){ for(int i = 0; i < 11; i++){ QApplication::postEvent(parent(), new ProgressEvent(i*10)); sleep(1); } } private: volatile bool m_stop; }; #endif // WORKTHREAD_H
-
主界面类
/*eventwidget.h*/
#ifndef EVENTWIDGET_H
#define EVENTWIDGET_H
#include <QWidget>
#include<QProgressBar>
#include "progressevent.h"
#include "workthread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class EventWidget; }
QT_END_NAMESPACE
class EventWidget : public QWidget
{
Q_OBJECT
public:
EventWidget(QWidget *parent = nullptr);
~EventWidget();
bool event(QEvent* event);
void closeEvent(QCloseEvent *event);
private:
Ui::EventWidget *ui;
QProgressBar* m_progress;
WorkThread* m_thread;
};
#endif // EVENTWIDGET_H
/*eventwidget.cpp*/
#include "eventwidget.h"
#include "ui_eventwidget.h"
EventWidget::EventWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::EventWidget)
{
ui->setupUi(this);
m_progress = new QProgressBar(this);
m_progress->move(10,10);
m_progress->setMinimum(0);
m_progress->setMaximum(100);
m_progress->setTextVisible(true);
m_progress->resize(100,30);
m_thread = new WorkThread();
m_thread->setParent(this);
m_thread->start();
}
EventWidget::~EventWidget()
{
if(m_thread->isRunning()){
m_thread->quit();
}
delete ui;
}
bool EventWidget::event(QEvent* event)
{
bool ret = true;
if(event->type() == ProgressEvent::TYPE){
ProgressEvent* evt = dynamic_cast<ProgressEvent*>(event);
if(evt!=NULL){
m_progress->setValue(evt->progress());
}
}
else{
ret = QWidget::event(event);
}
return ret;
}
void EventWidget::closeEvent(QCloseEvent *event)
{
m_thread->terminate();
}