Task 是Qgis 封装的多线程,用它可以不卡界面的实现后台的处理逻辑。本章主要用一个封装的例子来演示Task 的使用,同时演示如何用Task 调用Qgis 内部的进度条。
首先我们创建一个接口类
1、Work
IWork.h
#pragma once
#include "QgsFeedback.h"
class IWork
{
public:
IWork() {};
virtual ~IWork() {
};
virtual bool start() { return true; }; //开始函数
virtual void end() {};//结束函数
virtual QgsFeedback* feedback() const { return new QgsFeedback(); };
virtual void setFeedback(QgsFeedback* feedback) { };
virtual QString lastError() const { return QString(); };
};
IWork.cpp 是空的
创建一个实现该接口的BaseWork 抽象类,里面QgsFeedback 是和进度条有关的。
BaseWork.h
#pragma once
#include "IWork.h"
#include "QgsFeedback.h"
#include "QObject.h"
class BaseWork:public QObject, public IWork
{
Q_OBJECT
public:
BaseWork() = default;
BaseWork(QString name);
virtual ~BaseWork() {
};
QString name();
bool start() override; //开始函数
void end() override;//结束函数
QgsFeedback* feedback() const override;
void setFeedback(QgsFeedback* feedback) override;
QString lastError() const override;
protected:
QString mName;
double progress = 0.0;
double step = 100;
QgsFeedback* mFeedback;
QString mLastError;
private:
};
BaseWork.cpp
#include "BaseWork.h"
BaseWork::BaseWork(QString name):mName(name)
{
}
QString BaseWork::name()
{
return mName;
}
bool BaseWork::start()
{
return false;
}
void BaseWork::end()
{
}
QgsFeedback* BaseWork::feedback() const { return mFeedback; }
void BaseWork::setFeedback(QgsFeedback* feedback) { mFeedback = feedback; }
QString BaseWork::lastError() const { return mLastError; }
写一个继承该类的具体类,只要继承该类实现具体的接口即可。
2、Task
Qgs 的所有Task 必须继承QgsTask 的类,我们写一个通用类QgsProgressTask。
QgsProgressTask.h
#pragma once
#include <QObject>
#include "qgstaskmanager.h"
#include "qgsfeedback.h"
#include "IWork.h"
class QgsProgressTask : public QgsTask {
Q_OBJECT
public:
//构造函数
QgsProgressTask(IWork * work,QString name="进程");
QgsProgressTask(QString name);
~QgsProgressTask();
//重写run方法
bool run() override;
//重写cancel方法
void cancel() override;
//重新结束方法
void finished(bool result) override;
//该方法只在没有work的情况下使用
void complete();
QgsFeedback* feedback();
signals:
/**
* 当任务成功的时候可以发送信号给外部函数做其他处理
*/
void ZDComplete();
private:
IWork* mWork = nullptr;
//该属性只在没有work的情况下使用
bool miscomplete = false;
//回调
std::unique_ptr< QgsFeedback >mOwnedFeedback;
};
QgsProgressTask.cpp
#include "QgsProgressTask.h"
QgsProgressTask::QgsProgressTask(IWork* work,QString name ): QgsTask(name, QgsTask::CanCancel), mWork(work), mOwnedFeedback(new QgsFeedback())
{
work->setFeedback(mOwnedFeedback.get());
}
QgsProgressTask::QgsProgressTask(QString name): QgsTask(name, QgsTask::CanCancel), mOwnedFeedback(new QgsFeedback())
{
}
QgsProgressTask::~QgsProgressTask()
{
}
bool QgsProgressTask::run()
{
connect(mOwnedFeedback.get(), &QgsFeedback::progressChanged, this, &QgsProgressTask::setProgress);
connect(mOwnedFeedback.get(), &QgsFeedback::canceled, this, &QgsProgressTask::cancel);
if(mWork!=nullptr)
mWork->start();
else {
while (!miscomplete) {
int i=0;
}
}
return true;
}
void QgsProgressTask::cancel()
{
mOwnedFeedback->cancel();
QgsTask::cancel();
}
void QgsProgressTask::finished(bool result)
{
Q_UNUSED(result)
emit ZDComplete();
if (mWork != nullptr) {
mWork->end();
delete mWork;
mWork = nullptr;
}
}
void QgsProgressTask::complete()
{
miscomplete = true;
}
QgsFeedback* QgsProgressTask::feedback()
{
return mOwnedFeedback.get();
}
3、Task的使用
假设一个Work 继承自BaseWork,就可以用下面代码运行Task。Task一旦用taskManager 加入就开始运行了。
//开始任务
Work* mwork = new Work(mName);
QgsProgressTask* mtask = new QgsProgressTask(mwork, mName);
QObject::connect(mtask, SIGNAL(ZDComplete()), this, SLOT(end()));
QgsApplication::taskManager()->addTask(mtask);
4、进度条
可以用下面代码去设置进度条
mFeedback->setProgress(add);
//取消任务的回调
if (mFeedback->isCanceled())
{
}
5、小节
本章主要介绍了Task 的使用和进度条的设置。QgisTask 的本质是开启一个线程,其实可以用其他的多线程的方式代替,但是QgisTask 可以与qgis 自己的界面有更好 的衔接,更方便的调用qgis的界面。