1. 信号槽机制与界面更新
(1)子线程发射信号通知主线程进行界面更新
(2)主线程根据具体信号以及信号参数对界面组件进行修改
2. 事件机制与界面更新——解决方案:发送自定义事件
(1)自定义事件类用于描述界面更新细节
(2)在主窗口类中重写事件处理函数event
(3)使用postEvent函数(异步方式)发送自定义事件类对象
①子线程指定接受消息的对象为主窗口对象
②在event事件处理函数更新界面状态
【编程实验】子线程中更新界面组件
//StringEvent.h
#ifndef STRINGEVENT_H #define STRINGEVENT_H #include <QEvent> #include <QString> //自定义事件对象 class StringEvent : public QEvent { QString m_data; public: //提供全局唯一的Type值 static const QEvent::Type TYPE = static_cast<QEvent::Type>(QEvent::User + 0xFF); explicit StringEvent(QString data = ""); QString data(); //用于测试采用postEvent发送事件对象,被接收后会自动释放! ~StringEvent(); }; #endif // STRINGEVENT_H
//StringEvent.cpp
#include "StringEvent.h" #include <QDebug> StringEvent::StringEvent(QString data) : QEvent(TYPE) { m_data = data; qDebug() << "StringEvent::StringEvent(QString data)"; } QString StringEvent::data() { return m_data; } StringEvent::~StringEvent() { qDebug() << "StringEvent::~StringEvent()"; }
//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" #include <QApplication> #include "StringEvent.h" UpdateThread::UpdateThread(QObject *parent) : QThread(parent) { } void UpdateThread::run() { //发送事件对象 QApplication::postEvent(parent(), new StringEvent("Begin")); //parent为目标widget for(int i=0; i<10; i++){ QApplication::postEvent(parent(), new StringEvent(QString::number(i))); sleep(1); } QApplication::postEvent(parent(), new StringEvent("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; 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); connect(&m_thread, SIGNAL(updateUI(QString)), this, SLOT(appendText(QString))); //这里使用了一个技巧,将Widget这个组件传入线程中所供子线程访问。 m_thread.setParent(this);//传这个目标Widget组件给子线程 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 "Widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
3. 小结
(1)Qt中可以发送自定义事件在子线程中间接操作界面组件
(2)必须使用postEvent函数进行事件发送(异步方式)
(3)发送的事件对象必须在堆上创建
(4)子线程创建时必须附带目标对象的地址信息。
原文:http://www.cnblogs.com/5iedu/p/6498723.html