QT使用线程的两种方式
1.案例进度条
案例解析:
如图由组件一个进度条和三个按钮组成,当点击开始的时候进度条由0%到100%,点击暂停,进度条保持之前进度,再次点击暂停变为继续,点击停止按钮进度条停止。
案例流程:
1.创建qwidget工程
2.添加四个控件,转到槽函数
2.使用线程方式一
2.1创建一个类继承QThread,重写run方法
2.2mythread.cpp
#include "mythread.h"
#include <QDebug>
MyThread::MyThread()
{}
void MyThread::stop()
{running=false;
}
//暂停继续
void MyThread::threadStop(bool flag)
{pause=flag;
}
//重写run方法
void MyThread::run()
{qDebug()<<"线程id:"<<currentThreadId();while (1) {//触发信号while(running){while (pause) {msleep(100);}if(value>100)value=0;emit valChage(value++);msleep(100);}exit(0);}
}
2.3mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QDebug>
//继承QThread重写run方法
class MyThread : public QThread
{Q_OBJECT
public slots:void stop();void threadStop(bool flag);
signals:void valChage(int);
public:MyThread();void run();
private:int value=0;bool running=true;bool pause=false;
};#endif // MYTHREAD_H
2.4widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QProgressBar>
#include<QThread>
#include "mythread.h"
namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();
signals:void stop();void threadStop(bool);
private slots:void on_pushButton_clicked();void on_pushButton_3_clicked();void on_pushButton_2_clicked();private:Ui::Widget *ui;MyThread *mythread;
};
#endif // WIDGET_H
2.5widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked(){mythread= new MyThread();//绑定信号与槽函数connect(mythread,&MyThread::valChage,ui->progressBar,&QProgressBar::setValue);//延时connect(mythread,&MyThread::finished,mythread, &QObject::deleteLater);connect(this,&Widget::stop,mythread,&MyThread::stop);connect(this,&Widget::threadStop,mythread,&MyThread::threadStop);mythread->start();ui->pushButton->setEnabled(false);}void Widget::on_pushButton_3_clicked()
{emit stop();
}
void Widget::on_pushButton_2_clicked()
{static bool flag=true;if(flag){emit threadStop(true);ui->pushButton_2->setText("继续");flag=false;}else{emit threadStop(false);ui->pushButton_2->setText("暂停");flag=true;}
}
3.使用线程方式二
3.1创建类继承QObject
3.2qworker.h
这里的槽函数实现直接写在.h文件中,不够规范,只便与学习观看,切不要效仿。
#ifndef QWORKER_H
#define QWORKER_H
#include <QObject>
#include <QThread>
#include <QApplication>
class qworker : public QObject
{Q_OBJECT
public:explicit qworker(QObject *parent = nullptr);signals:void dataChanged(int);
public slots:void doWorking(){while (!sFlag) {if(current>=100)current=0;while (pFlag) {QThread::msleep(10);//接收来自外部进程的事件,否则收不到信号QApplication::processEvents();}emit dataChanged(current++);QThread::msleep(10);QApplication::processEvents();}sFlag=false;current=0;}void pause(bool flag){pFlag=flag;}void stop(){sFlag=true;}
private://进度条int current=0;//暂停bool pFlag=false;//停止bool sFlag=false;
};
#endif // QWORKER_H
3.3widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
//引入qworker.h
#include "qworker.h"namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();
signals:void working();void pause(bool);void stop();
private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();
c
private:Ui::Widget *ui;qworker *worker;QThread thread;
};
#endif // WIDGET_H
3.4widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);worker=new qworker();//移动到线程中worker->moveToThread(&thread);//开始connect(this,&Widget::working,worker,&qworker::doWorking);//暂停connect(this,&Widget::pause,worker,&qworker::pause);//停止connect(this,&Widget::stop,worker,&qworker::stop);connect(worker,&qworker::dataChanged,ui->progressBar,&QProgressBar::setValue);thread.start();
}
Widget::~Widget()
{delete ui;
}
void Widget::on_pushButton_clicked()
{emit working();
}void Widget::on_pushButton_2_clicked()
{static bool flag=true;if(flag){emit pause(true);flag=false;ui->pushButton_2->setText("继续");}else{emit pause(false);flag=true;ui->pushButton_2->setText("暂停");}
}
void Widget::on_pushButton_3_clicked()
{emit stop();
}
4.总结
两种方式都可以完成案例需求:
方式一:
1.通过继承QThread类重写run方法
2.重写类MyThread的虚函数void run();,即新建一个函数protected void run(),然后对其进行定义。
3.在需要用到多线程的地方,实例MyThread,然后调用函数MyThread::start()后,则开启一条线程,自动运行函数run()。
4.当停止线程时,调用MyThread::wait()函数,等待线程结束,并且回收线程资源。
方式二:
1.继承QObject类,创建对象。
2.通过moveToThread将派生类对象移动到一个线程中。
3.通过信号连接派生类的槽函数,将耗时的工作放到这个槽函数中运行。
4.用信号QThread::finished绑定槽函数QThread::deleteLatater(),在线程退出时,自动销毁该线程和相关资源。
5.通过QThread的start()函数开启多线程。