在Qt中,直接从子线程更新UI是不安全的,因为Qt的UI组件通常不是线程安全的。这意味着,如果你尝试在子线程中直接调用UI组件的方法,可能会导致程序崩溃或者不可预测的行为。为了安全地从子线程更新UI,Qt提供了几种机制:
信号和槽(Signals and Slots)
信号和槽是Qt中用于对象间通信的机制,它们可以用来在不同线程之间发送信息。当你需要从子线程更新UI时,可以创建一个信号,然后在子线程中发出这个信号。UI线程(主线程)连接这个信号,并在接收到信号时执行槽函数来更新UI。
mainwindow.h
主要是定义了2个槽,一个是自动生成的按钮点击后的槽,一个是新建接收子线程信号的槽;私有了子线程的变量
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "utils.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_clicked();public slots:void inc_num();private:Ui::MainWindow *ui;Utils *utils;
};
#endif // MAINWINDOW_H
mainwindow.cpp
绑定了信号与槽,并且在定义的两个槽中实现了逻辑
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow){//实例化子类, 并把子类的生命周期绑定到主类上utils = new Utils(this);//绑定信号与槽,utils是子线程,this绑定的就是当前主线程connect(utils,&Utils::send_inc_num,this,&MainWindow::inc_num);ui->setupUi(this);
}MainWindow::~MainWindow(){delete ui;
}//按钮点击的槽
void MainWindow::on_pushButton_clicked(){//调用子线程的方法utils->incNum();
}//接收send_inc_num信号的槽
void MainWindow::inc_num(){int num = ui->lineEdit->text().toInt()+1;ui->lineEdit->setText(QString::number(num));
}
utils.h
定义了信号
#ifndef UTILS_H
#define UTILS_H
#include <QObject>
#include <QDebug>class Utils : public QObject{Q_OBJECTsignals:void send_inc_num();public:Utils(QObject *parent = nullptr);void incNum();};#endif // UTILS_H
utils.cpp
子线程接收到主线程的调用后发送了信号
#include "utils.h"Utils::Utils(QObject *parent) : QObject(parent){}//发送信号
void Utils::incNum(){send_inc_num();
}