0x00 本文通过子线程产生的数据传递给主程,需要掌握如下知识
- <QMetaType>,向Qt的元对象系统中注册用户自定义数据类型。
<QThread>,创建子线程处理数据分担界面主线程占用的资源。
signal & slot 利用带参数的信号与槽来传递子线程到主线程的数据,
信号槽机制是Qt最大的特色功能,用于实例对象之间的通信;信号和槽都是成员函数,绑定一个对象的信号和另一个对象的槽函数,当前者发射出信号时,与之相对应的会触发后者的槽函数,这样两个对象间就完成了一次通信过程。
0x01 创建用户自定义结构体类型,并向Qt元对象系统声明该类型
- 以下代码声明了一个自定义的结构体类型。
- TransData结构体类型已经声明好了,要想在Qt某个类(一般是用户从Qt类中继承过来的类)中使用,还必须得注册该类型即qRegisterMetaType<TransData>("TransData");
//workthread.h
#ifndef USERDEFINE_H
#define USERDEFINE_H
#include <QMetaType> //Qt元类型系统头文件
struct TransData{
bool checkNework;
};
Q_DECLARE_METATYPE(TransData)
#endif // USERDEFINE_H
0x02 创建子线程,用自定义的结构体接收产生的数据
- 由于当前的子线程类中需要用到自定义的结构体类型,所以我们必须得在该类中注册要使用的自定义结构体类型,在子线程的构造函数中注册 TransData 数据类型。
我们需要把子线程中产生的数据传递给主线程,就要使用信号与槽机制,利用带参数的信号与槽进行传递数据,所以需要在子线程中声明一个信号,并在线程的任务函数中发射信号。
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
#include <QProcess>
#include "UserDefine.h"
class WorkThread : public QThread
{
Q_OBJECT
public:
WorkThread();
~WorkThread();
signals:
void sigTransData(TransData data); //自定义信号
private:
void run() override;
TransData data;
};
#endif // WORKTHREAD_H
#include "workthread.h"
#include <QDebug>
WorkThread::WorkThread()
{
//注册自定义结构体数据类型
qRegisterMetaType<TransData>("TransData");
}
WorkThread::~WorkThread()
{
qDebug() << __func__ << ":" << QThread::currentThreadId() << endl;
}
void WorkThread::run()
{
if(QProcess::execute("ping 127.0.0.1 -w 1") == 0){
data.checkNework = true;
emit sigTransData(data);
}else{
data.checkNework = false;
emit sigTransData(data);
}
}
0x03 在主线程中使用子线程产生的数据
- 我们要接收来自子线程产生的数据,需要声明并定义一个带参数的槽函数接收数据并处理数据。
- 下面代码中用到了Label控件和Push Button控件。
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include "workthread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWidget; }
QT_END_NAMESPACE
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
private slots:
void slotShowNetworkStatus(TransData data); //自定义槽函数
void on_btnStart_clicked();
private:
Ui::MainWidget *ui;
WorkThread* workThread;
};
#endif // MAINWIDGET_H
#include "mainwidget.h"
#include "ui_mainwidget.h"
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MainWidget)
{
ui->setupUi(this);
ui->lblNetworkStatus->setText("");
ui->btnStart->setText("start");
workThread = new WorkThread();
//关联信号和槽
connect(workThread, &WorkThread::sigTransData, this, &MainWidget::slotShowNetworkStatus);
}
MainWidget::~MainWidget()
{
delete ui;
delete workThread; //未指定父对象,手动销毁内存
}
void MainWidget::slotShowNetworkStatus(TransData data)
{
if(data.checkNework == true){
ui->lblNetworkStatus->setText("网络正常!!!");
}else{
ui->lblNetworkStatus->setText("网络存在故障!!!");
}
}
void MainWidget::on_btnStart_clicked()
{
if(ui->btnStart->text() == "start"){
workThread->start();
ui->btnStart->setText("stop");
}else{
workThread->terminate();
ui->btnStart->setText("start");
}
}