2023-02-05 QT 线程实现和计时器使用

第一种方式创建线程工作,继承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 ;

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容