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_OBJECT
public:
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_OBJECT
public:
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()函数开启多线程。