看了几篇关于线程和进程的文章,从表面理解,感觉线程和进程的起源,是先有进程后有线程,比较通俗一点什么是进程,进程就是电脑中任务管理区结束的,线程就是qq的聊天,界面刷新,上传文件等子功能。暂时这么理解吧。新
QThread类,它是所有线程类的基础,该类提供了很多低级的API对线程进行操作,每一个QThread对象都代表一个线程,使用该类开新线程并运行某段代码的方式一般有两种:
第一种方法是继承QThread并重写run函数,将耗时操作的代码放入这个函数里面执行就可以了。
第二种方法是调用QObject的moveToThread()函数将QObject对象移动到开的QThread线程对象中,这样QObject对象中所有的耗时操作都会在新线程中被执行。
首先,演示第一种方法,子类化QThread,重写run函数,把进度条的耗时放在run函数中,操作结果如下图:
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread();
protected:
void run() override;
signals:
void minNumToamin(int min);
};
#endif // MYTHREAD_H
MyThread.cpp
#include "mythread.h"
#include <QDebug>
MyThread::MyThread()
{
}
void MyThread::run()
{
int min = 0;
while(min<99)
{
msleep(50);
++min;
minNumToamin(min);
}
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mythread.h"
#include <QTimer>
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;
MyThread* m_thread;
QTimer *m_time;
public slots:
void getMinfromThread(int min);
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QProgressDialog>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->label->hide();
ui->progressBar->setAlignment(Qt::AlignHCenter);
m_time = new QTimer;
m_thread = new MyThread;
ui->progressBar->setValue(0);
ui->progressBar->setRange(0,100);
m_time->setSingleShot(true);
connect(m_time,&QTimer::timeout,[=](){ui->label->close();
ui->progressBar->setValue(0);
ui->pushButton->setText("开始下载");
});
connect(m_thread,&MyThread::minNumToamin,this,&Widget::getMinfromThread);
connect(m_thread,&QThread::finished,this,[=](){
QTimer::singleShot(4000,[=](){
ui->progressBar->setValue(100);
ui->label->show();
});
m_time->start(6000);
});
}
Widget::~Widget()
{
delete ui;
deleteLater();
}
void Widget::on_pushButton_clicked()
{
m_thread->start();
ui->pushButton->setText("停止下载");
}
void Widget::getMinfromThread(int min)
{
ui->progressBar->setValue(min);
}
第二种方法,将生存的QObeject通过接口moveToThread到新的线程中,如果不moveToThread,界面卡死,无法完成界面的操作,反之可以,效果如下:
图一是没有moveToThread:
图一是有moveToThread:
myObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
class myObject : public QObject
{
Q_OBJECT
public:
explicit myObject(QObject *parent = nullptr);
signals:
public slots:
void getTime();
};
#endif // MYOBJECT_H
myObject.cpp
#include "myobject.h"
#include <QDebug>
#include <QThread>
myObject::myObject(QObject *parent) : QObject(parent)
{
}
void myObject::getTime()
{
while (1)
{
qDebug()<<"hello world";
QThread::sleep(1);
}
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QThread>
#include <QWidget>
#include "myobject.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();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
myObject* obj;
QThread *m_thread;
signals:
void sendtoTime();
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QThread>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
obj = new myObject;
m_thread = new QThread;
obj->moveToThread(m_thread);
m_thread->start();
connect(this,&Widget::sendtoTime,obj,&myObject::getTime);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
ui->textEdit->append("Hello world");
}
void Widget::on_pushButton_2_clicked()
{
emit sendtoTime();
}