Qt——多线程与界面组件的通信 1.示例在子线程中创建QWidgetTestThread.h#ifndef TESTTHREAD_H #define TESTTHREAD_H #include QObject #include QThread class TestThread : public QThread { Q_OBJECT protected: void run(); public: explicit TestThread(QObject *parent nullptr); }; #endif // TESTTHREAD_HTestThread.cpp#include TestThread.h #include QWidget TestThread::TestThread(QObject *parent) : QThread{parent} {} void TestThread::run() { QWidget w; w.show(); exec(); }Widget.h#ifndef WIDGET_H #define WIDGET_H #include QWidget class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent nullptr); ~Widget() override; }; #endif // WIDGET_HWidget.cpp#include Widget.h #include TestThread.h Widget::Widget(QWidget *parent) : QWidget(parent) { TestThread* ptt new TestThread(); ptt-start(); } Widget::~Widget() default;main.cpp#include Widget.h #include QApplication int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return QCoreApplication::exec(); }运行结果会报错原因是所有界面组件的操作都只能在主线程中完成因此主线程也叫做UI线程2.子线程如何对界面组件进行更新解决方案——信号与槽在子线程类中定义界面组件的更新信号updateUI在主窗口类中定义更新界面组件的槽函数setInfo使用异步方式连接更新信号到槽函数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 nullptr); signals: void updateUI(QString text); }; #endif // UPDATETHREAD_HUpdateThread.cpp#include UpdateThread.h UpdateThread::UpdateThread(QObject *parent) : QThread{parent} {} void UpdateThread::run() { emit updateUI(begin); for(int i0; i10; i) { emit updateUI(QString::number(i)); sleep(1); } emit updateUI(End); }Widget.h#ifndef WIDGET_H #define WIDGET_H #include QWidget #include UpdateThread.h #include QPlainTextEdit class Widget : public QWidget { Q_OBJECT UpdateThread m_thread; QPlainTextEdit textEdit; protected slots: void appendText(QString text); public: explicit Widget(QWidget *parent nullptr); ~Widget() override; }; #endif // WIDGET_HWidget.cpp#include Widget.h #include QObject 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() default;main.cpp#include Widget.h #include QApplication int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return QCoreApplication::exec(); }运行结果本质分析子线程发射信号通知主线程界面更新请求主线程根据具体信号以及信号参数对界面组件进行修改3.是否有其他间接的方式可以让子线程更新界面组件的状态——发送自定义事件类自定义事件类用于描述界面更新细节在主窗口类中重写事件处理函数event使用postEvent函数异步发送自定义事件类对象子线程指定接受消息的对象为主窗口对象在event事件处理函数更新界面状态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_castType(QEvent::User 0xFF); explicit StringEvent(QString data ); QString data(); }; #endif // STRINGEVENT_HStringEvent.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_OBJECT protected: void run(); public: explicit UpdateThread(QObject *parent nullptr); }; #endif // UPDATETHREAD_HUpdateThread.cpp#include UpdateThread.h #include QApplication #include StringEvent.h UpdateThread::UpdateThread(QObject *parent) : QThread{parent} {} void UpdateThread::run() { QApplication::postEvent(parent(), new StringEvent(Begin)); for(int i0; i10; i) { QApplication::postEvent(parent(), new StringEvent(QString::number(i))); sleep(1); } QApplication::postEvent(parent(), new StringEvent(End)); }main.cpp#include Widget.h #include QApplication int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return QCoreApplication::exec(); }运行结果