Qt线程简单使用二:QObject~创建任务类
Posted 十一的杂文录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt线程简单使用二:QObject~创建任务类相关的知识,希望对你有一定的参考价值。
需求:
点击QPushButton按钮,QLabel中的数字,不断累加,一直到999。
做法:
创建任务类,用来完成任务,创建子线程,将任务类放到子线程中,点击QPushButton后,先发送信号启动任务类的任务,然后启动线程,通过任务类while循环,不断发送累加的数字会主线程,修改QLabel中的数字
其他:
一个任务类,可以创建多个任务,写法麻烦一点,视情况决定是否采用这种方法。
主要代码:
// MyThread.h #pragma once #include <QObject> #include <QThread> class MyWork : public QObject Q_OBJECT public: MyWork(QObject *parent=nullptr); ~MyWork(); void work(); signals: void sendNum(int num); ;
// MyThread.cpp #include "MyThread.h" MyWork::MyWork(QObject *parent) : QObject(parent) MyWork::~MyWork() void MyWork::work() int num = 0; while (num < 1000) emit sendNum(num); num++; QThread::msleep(5);
// QtWidgetsApplication1.cpp #include "MyThread.h" MyWidget::MyWidget(QWidget *parent) : QDialog(parent) ui.setupUi(this); // 1.创建子线程对象 QThread* t = new QThread; // 2.创建任务类对象 MyWork* work = new MyWork; // 3.将任务类对象移动到子线程对象中 work->moveToThread(t); // 开始工作 connect(this, &MyWidget::startWork, work, &MyWork::work); connect(work, &MyWork::sendNum, this, [=](int num) ui.label->setText(QString::number(num)); ); connect(ui.pushButton, &QPushButton::clicked, this, [=]() emit startWork(); t->start(); ); // 释放 // 第一种:创建的时候,添加this参数,这样会自动析构,例:QThread* t = new QThread(this); // 第二种,手动释放 connect(this, &MyWidget::destroy, [=]() t->quit(); t->wait(); delete t; delete work; );
Qt线程的简单使用
Qt中线程的一种创建方式,就是使用QObject::moveToThread()函数。如下,直接上源代码,可以把费时的任务放到doWork()方法里进行,不阻塞主线程。
1 #ifndef WORKER_H 2 #define WORKER_H 3 4 #include <QObject> 5 6 class Worker : public QObject 7 { 8 Q_OBJECT 9 10 public: 11 Worker(); 12 ~Worker(); 13 public slots: 14 void doWork(); 15 private: 16 17 }; 18 19 #endif // WORKERR_H
1 #include "Worker.h" 2 #include <QDebug> 3 4 Worker::Worker() 5 { 6 7 } 8 9 Worker::~Worker() 10 { 11 12 } 13 void Worker::doWork() 14 { 15 for (int i = 0;i < 10000;i++) 16 { 17 qDebug() << i; 18 } 19 }
需要在主程序中,关联相应的信号和槽,
1 m_pWorker = new Worker; 2 m_pWorkerThread = new QThread(this); 3 4 connect(m_pWorkerThread, SIGNAL(started()),m_pWorker, SLOT(doWork())); 5 connect(m_pWorkerThread, SIGNAL(finished()), m_pWorker, SLOT(deleteLater())); 6 m_pWorker->moveToThread(m_pWorkerThread);
同时在析构函数中,也要进行想要的资源释放,
1 disconnect(m_pWorkerThread, SIGNAL(started()),m_pWorker, SLOT(doWork())); 2 disconnect(m_pWorkerThread, SIGNAL(finished()), m_pWorker, SLOT(deleteLater())); 3 if (m_pWorkerThread) 4 { 5 if (m_pWorkerThread->isRunning()) 6 { 7 m_pWorkerThread->quit(); 8 m_pWorkerThread->wait(); 9 } 10 delete m_pWorkerThread; 11 m_pWorkerThread = NULL; 12 } 13 if (m_pWorker) 14 { 15 delete m_pWorker; 16 m_pWorker = NULL; 17 }
最后提一点,如果需要在doWork()函数传递参数中,涉及传递的参数是自定义的类型时,需要将其注册为元类型。
如下的示例,1.我将需要计算的数据先进行预处理之后,发送我自定义的geoDataReady信号。
2.在线程中进行几何计算,完成之后,又将计算完成之后的数据发送回主函数。如下。
1 qRegisterMetaType<std::vector<MyGeometry*>>("std::vector<MyGeometry* >"); 2 //在线程中进行几何运算 3 m_pGeoWorker = new CMyWork; 4 connect(this, SIGNAL(geoDataReady(const std::vector<MyGeometry> &)), m_pGeoWorker, SLOT(get(const std::vector<MYGeometry* > &))); 5 connect(m_pGeoWorker, SIGNAL(geoResultCompleted(const std::vector<MYGeometry* > &)), this, SLOT(draw(const std::vector<MYGeometry* > &))); 6 connect(&m_geoThread, SIGNAL(finished()), m_pGeoWorker, SLOT(deleteLater())); 7 m_pGeoWorker->moveToThread(&m_geoThread); 8 m_geoThread.start();
以上是关于Qt线程简单使用二:QObject~创建任务类的主要内容,如果未能解决你的问题,请参考以下文章