Qt两种线程实现方法
方法一基于Qt版本4
创建一个类,继承于QThread类,重写run函数。
// 1. 创建一个子类,继承于QThread
class MyThread : public QThread {
// ...
};
// 2. 重写父类中的 run() 方法,该函数主要实现要,要处理复杂业务逻辑。
class MyThread : public QThread {
protected:
void run();
};
// 3. 在主线程中创建一个子线程对象
MyThread *myThread = new MyThread(this);
// 4. 启动子线程
myThread->start();
使用这种方法子线程没办法直接调用界面部件类的控件
需要使用信号与槽机制
threadwidget.h
#ifndef THREADWIDGET_H
#define THREADWIDGET_H
#include <QThread>
class ThreadWidget : public QThread
{
Q_OBJECT
public:
explicit ThreadWidget(QObject *parent = nullptr);
protected:
virtual void run() override;
signals:
void isDone();
};
#endif // THREADWIDGET_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
threadwidget.cpp
#include "threadwidget.h"
#include <QDebug>
ThreadWidget::ThreadWidget(QObject *parent)
: QThread{parent}
{
}
/**
* @brief 子线程的程序入口
* 注意:子线程没办法直接访问界面部件类的
*/
void ThreadWidget::run() {
qDebug() << QThread::currentThreadId();
QThread::sleep(5);
qDebug() << "子线程ID : " << QThread::currentThreadId();
emit isDone();
return ;
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "threadwidget.h"
#include <QTimer>
#include <QThread>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
#if 0
QTimer *timer = new QTimer(this);
static int i = 0;
connect(timer, &QTimer::timeout, this, [=](){
ui->label->setNum(i++);
});
connect(ui->pushButton, &QPushButton::clicked, this, [=](){
// 判断计时器有没有开启
if(!timer->isActive()) timer->start(500);
// 模拟一个复杂的处理, 5s
QThread::sleep(5);
// timer->stop();
});
#endif
// 创建线程对象
ThreadWidget *thread = new ThreadWidget(this);
QTimer *timer = new QTimer(this);
static int i = 0;
connect(timer, &QTimer::timeout, this, [=](){
ui->label->setNum(i++);
});
connect(ui->pushButton, &QPushButton::clicked, this, [=](){
if(!timer->isActive()) {
timer->start(500);
// 开启子线程
thread->start();
}
qDebug() << "主线程的ID" << QThread::currentThreadId();
});
// 通过信号与槽机制修改窗口控件
connect(thread, &ThreadWidget::isDone, this, [=](){
if(timer->isActive())timer->stop();
});
// 窗口关闭的话关闭线程
connect(this, &QWidget::destroyed, this, [=](){
// 等待子线程处理完成后才能退出
thread->quit();
thread->wait();
});
}
Widget::~Widget()
{
delete ui;
}
方法一基于Qt版本5
创建一个类,继承于QObject类,将此类移动到线程中运行。
// 1. 创建一个类,继承于QObject
class MyThread : public QObject {
// ...
};
// 2. 在此类中添加公共的成员函数,此函数体就是要执行的业务逻辑
class MyThread : public QObject {
public:
void handler();
};
// 3. 在主线程中创建一个 QThread 对象
QThread *sub = new QThread(this);
// 4. 在主线程中创建一个工作对象,不允许指定父对象
MyThread *work = new MyThread;
// 5. 将创建好的 sub 对象移动到 word 对象中
work->moveToThread(sub);
// 6. 启动子线程,还需要调用handler函数,才能运行work线程
sub->start();
connect(this, &Widget::startThread, work, &MyThread::fun, Qt::QueuedConnection);