Qt多线程的学习与使用,仅供参考,不足之处请多多指教.
Qt中多线程使用方式有2种:一种是直接继承QThread,重写run()函数;另一种是利用QObject(QObject是所有Qt对象的基类) 的 moveToThread()函数,通过事件驱动的方式启用多线程.
一:继承QThread,重写run()函数.
mythread.h
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread();
virtual void run();
signals:
void signalSendImage(QImage);
};
mythread.cpp
#include "mythread.h"
MyThread::MyThread()
{
}
void MyThread::run()
{
QImage image("../dl.png");
QThread t;
qDebug()<<t.currentThreadId();
emit signalSendImage(image);
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MyThread *t = new MyThread();
connect(ui->pushButton,&QPushButton::clicked,[=](){
//t->run(); //这样调用并不会开启新线程,直接运行到了run()函数,如果run'()里面有很多消耗比较大还会卡住主线程,不能做其他操作
t->start(); //开启新线程单独处理run()函数中的逻辑,UI界面(主程序)任然可以做其他操作
});
connect(t,&MyThread::signalSendImage,[=](QImage image){
ui->label->clear();
ui->label->setPixmap(QPixmap::fromImage(image));
});
}
二:moveToThread()函数,通过事件驱动的方式启用多线程.
将需要在线程中处理的业务放在独立的类中,由主线程创建该对象后,将该对象交给指定的线程运行,而且可以将多个类似的对象交给同一个线程.
列:线程读取图片发送给主程序ui显示图片,原理:建立readimage工作类处理得到图片后发送信号给主线程,主线程结束后通过重写paintEvent()重绘事件,绘制图片.定时返回进度条数据更新进度条
readimage 处理图片和处理数据类
readimage.h
class ReadImage : public QObject
{
Q_OBJECT
public:
explicit ReadImage(QObject *parent = nullptr);
int s = 0;
signals:
void signalToTell(QImage image); //告知主程序读取图像完成
void signalInt(int s);
public slots:
void onReadImage();
void onLoad();
};
readimage.cpp
#include "readimage.h"
#include <QDebug>
#include <QThread>
ReadImage::ReadImage(QObject *parent) : QObject(parent)
{
}
void ReadImage::onReadImage()
{
QImage image("../dl.png");
emit signalToTell(image);
QThread t;
qDebug()<<t.currentThreadId();
}
void ReadImage::onLoad()
{
if(s<=100)
s++;
qDebug()<<QThread::currentThreadId();
emit signalInt(s);
}
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void paintEvent(QPaintEvent *event);
private slots:
private:
Ui::MainWindow *ui;
QThread *mthread;
ReadImage *mr;
QImage mimg;
int s;
};
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QImage>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->horizontalSlider->setValue(0);
QTimer *timer = new QTimer();
mthread = new QThread;
mr = new ReadImage;
connect(ui->pushButton,&QPushButton::clicked,mr,&ReadImage::onReadImage);
connect(mr,&ReadImage::signalToTell,[=](QImage image){ //处理图片
this->mimg = image;
update(); //触发窗口重绘事件paintEvent()
});
connect(timer,SIGNAL(timeout()),mr,SLOT(onLoad()));
connect(mr,&ReadImage::signalInt,[=](int i){ //处理进度条数据
this->s = i;
update();
});
mr->moveToThread(mthread);
timer->start(500);
mthread->start();
}
MainWindow::~MainWindow()
{
delete ui;
mthread->quit(); //结束线程的事件循环
//mthread->terminate(); //强制终止线程的运行
mthread->wait(); //等待线程运行完成
}
void MainWindow::paintEvent(QPaintEvent *event)
{
ui->label->setPixmap(QPixmap::fromImage(mimg));
ui->horizontalSlider->setValue(s);
}
效果展示: