【Qt】 Qt中实时更新UI程序示例

00. 目录

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_H

workthread.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_NAMESPACE

class WorkThread;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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_H

mainwindow.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_H

workthread.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_NAMESPACE

class WorkThread;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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_H

mainwindow.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

© 版权声明
THE END
喜欢就支持一下吧
点赞870 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容