【Qt】 Qt中实时更新UI程序示例
00. 目錄
文章目錄
- 00. 目錄
- 01. 概述
- 02. 開發環境
- 03. 實時更新UI(非信號與槽)
- 04. 實時更新UI(信號與槽)
- 05. 源碼下載
- 06. 附錄
01. 概述
Qt在運行時會開啟一個主線程,如果沒有開啟工作線程的話,所有界面上的操作都是在主線程,包括更新界面或者處理數據等操作。我們都知道如果處理數據比較多的話,最好是在單獨開啟一個線程來處理數據,這樣就不會影響主線程的運行。
02. 開發環境
Windows系統:Windows10
Qt版本:Qt5.15或者Qt6
03. 實時更新UI(非信號與槽)
QT中不建議工作線程中更新界面。
workthread.h
#ifndef WORKTHREAD_H #define WORKTHREAD_H#include <QThread>class MainWindow; class QLabel;class WorkThread : public QThread {Q_OBJECT public:WorkThread(QObject *parent);~WorkThread();void setObject(MainWindow *obj);void setLabel(QLabel *l);void stop();protected:void run();private:MainWindow *mainObject = nullptr;QLabel *label = nullptr;int i = 0;volatile bool stopped = false; };#endif // WORKTHREAD_Hworkthread.cpp
#include "workthread.h" #include "mainwindow.h"#include <QLabel> #include <QDebug>WorkThread::WorkThread(QObject *parent):QThread(parent) {stopped = false; }WorkThread::~WorkThread() {}void WorkThread::setObject(MainWindow *obj) {mainObject = obj; }void WorkThread::setLabel(QLabel *l) {label = l; }void WorkThread::run() {qDebug() << "線程開始運行";while(!stopped){msleep(1);i++;//mainObject->runInThread();label->setText(QString("當前計數為:%1").arg(i));}//下次啟動stopped = false; }//暫停線程 void WorkThread::stop() {stopped = true;qDebug() << "線程已經暫停"; }mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>#include "workthread.h"QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass WorkThread;class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void runInThread();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();private:Ui::MainWindow *ui;WorkThread *thread = nullptr;int count = 0; }; #endif // MAINWINDOW_Hmainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h"#include "workthread.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);thread = new WorkThread(this);thread->setObject(this);thread->setLabel(ui->label);ui->pushButton->setEnabled(true);ui->pushButton_2->setEnabled(false); }MainWindow::~MainWindow() {delete ui; }void MainWindow::runInThread() {count++;ui->label->setText(QString("當前計數為: %1").arg(count)); }//啟動線程 void MainWindow::on_pushButton_clicked() {if (nullptr != thread){thread->start();}ui->pushButton->setEnabled(false);ui->pushButton_2->setEnabled(true); }//暫停線程 void MainWindow::on_pushButton_2_clicked() {if (nullptr != thread){thread->stop();}ui->pushButton->setDisabled(false);ui->pushButton_2->setDisabled(true); }主界面
04. 實時更新UI(信號與槽)
workthread.h
#ifndef WORKTHREAD_H #define WORKTHREAD_H#include <QThread>class MainWindow; class QLabel;struct Student {int id;char sex;QString name; };//聲明元類型 Q_DECLARE_METATYPE(Student)class WorkThread : public QThread {Q_OBJECT public:WorkThread(QObject *parent);~WorkThread();void stop();protected:void run();signals:void sigCount(Student s);private:int i = 0;volatile bool stopped = false; };#endif // WORKTHREAD_Hworkthread.cpp
#include "workthread.h" #include "mainwindow.h"#include <QLabel> #include <QDebug>WorkThread::WorkThread(QObject *parent):QThread(parent) {//注冊自定義類型qRegisterMetaType<Student>();stopped = false; }WorkThread::~WorkThread() {}void WorkThread::run() {qDebug() << "線程開始運行";while(!stopped){i++;//發送信號Student s;s.id = i;s.sex = 'M';s.name = "lily";emit sigCount(s);msleep(1);}//下次啟動stopped = false; }//暫停線程 void WorkThread::stop() {stopped = true;qDebug() << "線程已經暫停"; }mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>#include "workthread.h"QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass WorkThread;class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void slotSetValue(Student s);private:Ui::MainWindow *ui;WorkThread *thread = nullptr; }; #endif // MAINWINDOW_Hmainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h"#include "workthread.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);thread = new WorkThread(this);ui->pushButton->setEnabled(true);ui->pushButton_2->setEnabled(false);connect(thread, &WorkThread::sigCount, this, &MainWindow::slotSetValue); }MainWindow::~MainWindow() {delete ui; }//啟動線程 void MainWindow::on_pushButton_clicked() {if (nullptr != thread){thread->start();}ui->pushButton->setEnabled(false);ui->pushButton_2->setEnabled(true); }//暫停線程 void MainWindow::on_pushButton_2_clicked() {if (nullptr != thread){thread->stop();}ui->pushButton->setDisabled(false);ui->pushButton_2->setDisabled(true); }//槽函數 void MainWindow::slotSetValue(Student( s)) {ui->label->setText(QString("當前值為: %1 %2 %3").arg(s.id).arg(s.sex).arg(s.name)); }主界面
【溫馨提示】
如果要在Qt信號槽中使用自定義類型,需要注意使用qRegisterMetaType對自定義類型進行注冊,當然在不跨線程時使用自定義類型signal/slot來傳遞,可能不會出現什么問題;一旦涉及跨線程就很容易出錯,回想下信號槽的作用就是用來對象與對象之間通信的,難免會跨線程,建議在使用自定義類型利用信號槽通信時,最好先通過qRegisterMetaType()將自定義類型進行注冊,以免出錯。
總結qRegisterMetaType使用方法如下:
1、注冊位置:在第一次使用此類鏈接跨線程的signal/slot之前,一般在當前類的構造函數中進行注冊;
2、注冊方法:在當前類的頂部包含:#include ,構造函數中加入代碼:qRegisterMetaType(“Myclass”);
3、Myclass的引用類型需單獨注冊:qRegisterMetaType(“Myclass&”);
05. 源碼下載
下載:實時更新UI(信號與槽方式).rar
06. 附錄
6.1 Qt教程匯總
網址:https://dengjin.blog.csdn.net/article/details/115174639
總結
以上是生活随笔為你收集整理的【Qt】 Qt中实时更新UI程序示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Qt】创建线程程序示例
- 下一篇: 【机器视觉】 Halcon代码导出高级语