第一种方式创建线程工作,继承QThread,实现run纯虚函数
1、需要创建一个继承QThread的类
2、在类里面实现run() 纯虚函数
3、实例化这个类,调用父类函数start(),回调函数run()开始执行。
4、还可以在这个类写一个信号,信号不需要实现,信号也可以带参数,如果带参数,需要槽函数匹配一样类型参数接收,这个不需要赋值,槽函数参数自动接收。
通过绘制一个lcd计数器,和一个按钮,点击按钮实现,通过计时器每隔500ms触发一次timeout信号,在构造函数,使用timeout信号和计数器加一绑定一起,每隔500ms,计数器就加一,但是如果,timer启动之后有一个耗时的工作,那么只能等耗时的工作完成之后,才会触发timeout信号,导致计时器不能同时工作,所以需要一个开启一个线程,把耗时工作,放入线程里面。这样界面的lcd就可以正常启动,界面也不会卡死。
二话不说上代码
自定义线程头文件
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class myThread : public QThread
{
Q_OBJECT
public:
explicit myThread(QThread *parent = nullptr);
private:
protected:
//继承QThread run 纯虚函数 纯虚函数一定要写实现
//线程内容在run函数里面写
//自定义线程,回调函数,当自定义线程 myThread.start(),会进入到这里
void run() override;
signals:
//信号,可以写一个信号,当自定义线程里面内容实现完成,发生信号通知线程内容已完成。
void done();
};
#endif // MYTHREAD_H
自定义线程.cpp文件
#include "mythread.h"
myThread::myThread(QThread *parent) : QThread(parent)
{
}
void myThread::run()
{
//耗时工作
//等耗时工作完成,emit signals ,通知外部,耗时工作已完成
sleep(5);
emit done();
}
Widget 头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QTimer>
#include<QThread>
#include"mythread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
QTimer *timer;
myThread *m_T;
};
#endif // WIDGET_H
Widget .cpp文件
#include "widget.h"
#include "ui_widget.h"
#include<QElapsedTimer>
#include<QtDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//实例化计时器
timer = new QTimer();
//实例化线程
m_T= new myThread();
connect(timer,&QTimer::timeout,this,[=](){
static int num =0;
ui->lcdNumber->display(num++);
});
connect(m_T,&myThread::done,this,[=](){
qDebug()<<"线程工作完成";
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
//判断计时器是否是处于活动
//以免计时器重复运行。
if(true==timer->isActive())
{
return;
}
timer->start(500);
//QT 计时函数 QElapsedTimer
//time.start() 开始计时
//time.elapsed() 计时结果
// QElapsedTimer time;
// time.start();
// QThread::sleep(3);
// qDebug()<<time.elapsed();
//线程开始,默认线程优先级,参数(线程优先级)
//通过debug可以得到线程运行,通过得到时间函数,得不出线程工作时间。
QElapsedTimer time;
time.start();
m_T->start();
qDebug()<<time.elapsed();
}
第二种创建线程工作,调用工作类(继承QObject)对象的moveToThread方法
1、先创建工作类,在工作类里面写一个槽函数,一个信号(主要是线程执行槽函数通知外部)
#ifndef WORK_H
#define WORK_H
#include <QObject>
#include<QDebug>
class work : public QObject
{
Q_OBJECT
public:
explicit work(QObject *parent = nullptr);
public slots:
//线程工作内容
void dowork(int parameter);
signals:
//线程完成工作内容发送的信号
void resultReady(const int result);
};
#endif // WORK_H
#include "work.h"
work::work(QObject *parent)
: QObject{parent}
{
}
void work::dowork(int parameter)
{
//耗时工作
qDebug()<<"work start";
for(int i =0;i<1000;++i)
{
++parameter;
}
//耗时工作完成发出完成信号
emit resultReady(parameter);
}
2、创建一个触发或者说是连接线程和工作类的类,在类里面声明一个QThred的全局变量。实例化一个工作类对象,调用这个对象的moveToThread类,传入QThread变量。
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include<QThread>
#include<QDebug>
#include"work.h"
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
explicit Controller(QObject *parent = nullptr);
~Controller()override;
public slots:
//处理线程执行的结果
static void handleResults(int result);
signals:
//发送信号,触发线程工作
void operate1(const int);
};
#endif // CONTROLLER_H
通过触发信号和工作的槽函数连接起来,启动线程,触发信号,线程就执行了。
#include "controller.h"
Controller::Controller(QObject *parent)
: QObject{parent}
{
//工作类实例化
auto *worker = new work;
//将worker对象的事件循环全部交由workerThread线程
worker->moveToThread(&workerThread);
//触发信号,开始工作。
connect(this,&Controller::operate1,worker,&work::dowork);
//线程执行完成发出信号,接收信号执行下一个动作;
connect(worker,&work::resultReady,this,&Controller::handleResults);
//线程结束时候销毁
connect(&workerThread,&QThread::finished,worker,&QThread::deleteLater);
//启动线程
workerThread.start();
//触发线程工作
emit operate1(0);
}
Controller::~Controller()
{
workerThread.quit();
workerThread.wait();
}
void Controller::handleResults(int result)
{
qDebug() << "receive the resultReady signal" ;
qDebug() << "\tCurrent thread ID: " << QThread::currentThreadId() << '\n' ;
qDebug() << "\tThe last result is: " << result ;
}