Qt通过对象moveToThread实现多线程,避免包含大量计算任务的子线程堵塞界面主线程,通过信号槽和主线程传递数据。
实现方式:
对于包含复杂复杂耗时计算任务的逻辑功能封装为ChildThread(继承自QObject),通过moveToThread函数可以把ChildThread转移到一个新的子线程里。把需要进行复杂耗时的计算任务的入口函数申明为槽函数,界面主线程所在类的槽函数里实现启动子线程逻辑,new一个QThread对象,并把ChildThread的实例化move到这个子线程中去,连接好相应的信号和槽,在子线程发射信号计算结束信号resultReady,主线程接收信号。
具体实现如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "childthread.h"
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QThread * thread;
ChildThread * work;
void showUi();
int var ;
int num=0;
private:
Ui::MainWindow *ui;
signals:
void resultReady(int);
public slots:
void handleResults(int);
void sure();
void startChildThread();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "childthread.h"
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QPushButton>
#include <QMessageBox>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton *btn1=new QPushButton("启动子线程");
QWidget * w=new QWidget;
QVBoxLayout *v=new QVBoxLayout;
v->addWidget(btn1);
w->show();
w->setLayout(v);
this->setCentralWidget(w);
connect(btn1,SIGNAL(clicked(bool)),this,SLOT(startChildThread()));
}
void MainWindow::startChildThread(){
//如果不单独开一个线程,子线程中涉及到大量计算,界面可能会卡顿
qDebug()<<"1.startChildThread";
thread = new QThread();
work = new ChildThread;
//线程启动以后执行 ChildThread中的childDoWork函数
connect(thread, SIGNAL(started()), work, SLOT(childDoWork()));
connect(work, SIGNAL(resultReady(int)), this, SLOT(handleResults(int)));
//connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
work->moveToThread(thread);
thread->start();
}
void MainWindow::handleResults(int var){
qDebug()<<"3.MainWindow::handleResults()";
qDebug()<<"MainWindow var="<<var;
}
MainWindow::~MainWindow()
{
delete ui;
}
#ifndef CHILDTHREAD_H
#define CHILDTHREAD_H
#include <QObject>
class ChildThread : public QObject
{
Q_OBJECT
public:
explicit ChildThread(QObject *parent = nullptr);
int var=0;
signals:
void resultReady(int);
public slots:
void childDoWork();
};
#endif // CHILDTHREAD_H
#include "childthread.h"
#include <QDebug>
#include <QThread>
ChildThread::ChildThread(QObject *parent) : QObject(parent)
{
}
void ChildThread::childDoWork(){
qDebug()<<"2.childDoWork";
for(int i=0;i<1000000;i++){
var++;
}
emit resultReady(var);
}