【Qt】 Qt中实时更新UI程序示例
00. 目錄
文章目錄
- 00. 目錄
- 01. 概述
- 02. 開(kāi)發(fā)環(huán)境
- 03. 實(shí)時(shí)更新UI(非信號(hào)與槽)
- 04. 實(shí)時(shí)更新UI(信號(hào)與槽)
- 05. 源碼下載
- 06. 附錄
01. 概述
Qt在運(yùn)行時(shí)會(huì)開(kāi)啟一個(gè)主線程,如果沒(méi)有開(kāi)啟工作線程的話,所有界面上的操作都是在主線程,包括更新界面或者處理數(shù)據(jù)等操作。我們都知道如果處理數(shù)據(jù)比較多的話,最好是在單獨(dú)開(kāi)啟一個(gè)線程來(lái)處理數(shù)據(jù),這樣就不會(huì)影響主線程的運(yùn)行。
02. 開(kāi)發(fā)環(huán)境
Windows系統(tǒng):Windows10
Qt版本:Qt5.15或者Qt6
03. 實(shí)時(shí)更新UI(非信號(hào)與槽)
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() << "線程開(kāi)始運(yùn)行";while(!stopped){msleep(1);i++;//mainObject->runInThread();label->setText(QString("當(dāng)前計(jì)數(shù)為:%1").arg(i));}//下次啟動(dòng)stopped = false; }//暫停線程 void WorkThread::stop() {stopped = true;qDebug() << "線程已經(jīng)暫停"; }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("當(dāng)前計(jì)數(shù)為: %1").arg(count)); }//啟動(dòng)線程 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. 實(shí)時(shí)更新UI(信號(hào)與槽)
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) {//注冊(cè)自定義類型qRegisterMetaType<Student>();stopped = false; }WorkThread::~WorkThread() {}void WorkThread::run() {qDebug() << "線程開(kāi)始運(yùn)行";while(!stopped){i++;//發(fā)送信號(hào)Student s;s.id = i;s.sex = 'M';s.name = "lily";emit sigCount(s);msleep(1);}//下次啟動(dòng)stopped = false; }//暫停線程 void WorkThread::stop() {stopped = true;qDebug() << "線程已經(jīng)暫停"; }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; }//啟動(dòng)線程 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); }//槽函數(shù) void MainWindow::slotSetValue(Student( s)) {ui->label->setText(QString("當(dāng)前值為: %1 %2 %3").arg(s.id).arg(s.sex).arg(s.name)); }主界面
【溫馨提示】
如果要在Qt信號(hào)槽中使用自定義類型,需要注意使用qRegisterMetaType對(duì)自定義類型進(jìn)行注冊(cè),當(dāng)然在不跨線程時(shí)使用自定義類型signal/slot來(lái)傳遞,可能不會(huì)出現(xiàn)什么問(wèn)題;一旦涉及跨線程就很容易出錯(cuò),回想下信號(hào)槽的作用就是用來(lái)對(duì)象與對(duì)象之間通信的,難免會(huì)跨線程,建議在使用自定義類型利用信號(hào)槽通信時(shí),最好先通過(guò)qRegisterMetaType()將自定義類型進(jìn)行注冊(cè),以免出錯(cuò)。
總結(jié)qRegisterMetaType使用方法如下:
1、注冊(cè)位置:在第一次使用此類鏈接跨線程的signal/slot之前,一般在當(dāng)前類的構(gòu)造函數(shù)中進(jìn)行注冊(cè);
2、注冊(cè)方法:在當(dāng)前類的頂部包含:#include ,構(gòu)造函數(shù)中加入代碼:qRegisterMetaType(“Myclass”);
3、Myclass的引用類型需單獨(dú)注冊(cè):qRegisterMetaType(“Myclass&”);
05. 源碼下載
下載:實(shí)時(shí)更新UI(信號(hào)與槽方式).rar
06. 附錄
6.1 Qt教程匯總
網(wǎng)址:https://dengjin.blog.csdn.net/article/details/115174639
總結(jié)
以上是生活随笔為你收集整理的【Qt】 Qt中实时更新UI程序示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Qt】创建线程程序示例
- 下一篇: 【机器视觉】 HDevelop语言基础(