Qt中在子線程中刷新UI的方法
在Qt中UI界面并不是線程安全的,意味著在子線程中不能隨意操作UI界面組件(比如按鈕、標簽)等,如果強行操作這些組件有可能會導致程序崩潰。那么在Qt中如何在子線程中刷新UI控件呢?
兩種方法:
方法一:使用信號槽機制。
第一步:創建一個QWidget項目,并且在其中添加一個繼承自QThread的子線程類QWorkThread,如下:
#ifndef QWORKTHREAD_H
#define QWORKTHREAD_H#include <QObject>
#include<QThread>class QWorkThread : public QThread
{Q_OBJECT
public:explicit QWorkThread(QThread *parent = nullptr);QWorkThread(QWidget* pWidget,QThread *parent = nullptr);QWidget* m_pWidget = nullptr;protected:virtual void run() override;signals:void UpdateUI(QString strInfo);
};#endif // QWORKTHREAD_H
說明:
1.自定義一個信號UpdateUI用來刷新主線程UI。
2.重寫run函數,使用emit 發射UpdateUI信號如下:
void QWorkThread::run()
{emit UpdateUI("刷新控件");
}
第二步:在MainWindow中定義一個槽函數,用來響應UpdateUI信號:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();public slots:void UpdateWidgetUI(QString strInfo);private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
第三步:調用connect連接UpdateUI信號和UpdateWidgetUI槽函數,刷新UI:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qworkthread.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QWorkThread* pThread = new QWorkThread(ui->label);connect(pThread,&QWorkThread::UpdateUI,this,&MainWindow::UpdateWidgetUI);connect(pThread,&QThread::finished, pThread, &QThread::deleteLater);pThread->start();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::UpdateWidgetUI(QString strInfo)
{ui->label->setText(strInfo);
}
程序運行前后結果:
方法二:使用invokeMethod()方法。
第一步:增加一個帶QWidget的構造函數,并且在QWorkThread定義一個QWidget 類型的變量用來保存要刷新的控件。如上QWorkThread頭文件中。
第二步:修改QWorkThread::run方法如下:
void QWorkThread::run()
{if(m_pWidget != nullptr)QMetaObject::invokeMethod(m_pWidget,"setText",Qt::QueuedConnection,Q_ARG(QString,"刷新控件2"));
}
其中調用QMetaObject::invokeMethod方法。
程序運行結果如下:
雖然Qt不允許子線程直接操作UI界面,但通過信號與槽機制或invokeMethod()
方法,子線程和UI線程可以安全地進行交互。這些機制確保了多線程程序的穩定性,避免了UI更新時可能出現的線程安全問題。
參考文章:Qt/C++面試【速通筆記五】—子線程與GUI線程安全交互