0
点赞
收藏
分享

微信扫一扫

六十九、Qt之开启子线程执行业务,并使用“自定义事件”获取子线程结果实例

一、概况

1.自定义事件

class AlgRunnable;

class ExcutedEvent : public QEvent
{
public:
ExcutedEvent(AlgRunnable *r) :
QEvent(evType()),
m_runnable(r)
{

}
AlgRunnable *m_runnable;
static QEvent::Type evType()
{
if (s_evType == QEvent::None) {
s_evType = (QEvent::Type)registerEventType();
}
return s_evType;
}

private:
static QEvent::Type s_evType;
};

QEvent::Type ExcutedEvent::s_evType = QEvent::None;

2.开启子线程,执行业务,并在执行任务后,发送事件

class AlgRunnable : public QRunnable
{
.......
void run()
{
//执行图像算法
g_functions[m_alg](m_sourceFilePath, m_destFilePath);
//执行图形处理完毕后,发送自定义事件给 ImageProcessor
QCoreApplication::postEvent(m_observer, new ExcutedEvent(this));
}

......
};

3.拦截并判断事件,做出后续响应

class ImageProcessorPrivate : public QObject
{
........
//拦截并判断事件是否为自定义事件
bool event(QEvent *event)
{
//当接收到自定义事件,表明图形处理已经完毕,发送 finished() 信号
if (event->type() == ExcutedEvent::evType()) {
ExcutedEvent *ee = (ExcutedEvent*)event;
if (m_runnables.contains(ee->m_runnable)) {
m_notifiedAlg = ee->m_runnable->m_alg;
m_notifiedSourceFile = ee->m_runnable->m_sourceFilePath;
emit m_processor->finished(ee->m_runnable->m_destFilePath);
m_runnables.removeOne(ee->m_runnable);
}
delete ee->m_runnable;
return true;
}
return QObject::event(event);
}
//开启子线程,执行耗时业务
void process(QString sourceFile, ImageProcessor::ImageAlg alg)
{
QFileInfo fi(sourceFile);
QString destFile = QString("%1/%2_%3").arg(m_tempPath).arg((int)alg).arg(fi.fileName());
AlgRunnable *r = new AlgRunnable(sourceFile, destFile, alg, this);
m_runnables.append(r);
r->setAutoDelete(false); //将自动删除设置为 false
//用线程池,执行线程
QThreadPool::globalInstance()->start(r);
}

.....
};

二、完整代码

ImageProcessor.h

#ifndef IMAGEPROCESSOR_H
#define IMAGEPROCESSOR_H

#include <QObject>

class ImageProcessorPrivate;

class ImageProcessor : public QObject
{
Q_OBJECT
Q_ENUMS(ImageAlg)
Q_PROPERTY(QString sourceFile READ sourceFile)
Q_PROPERTY(ImageAlg alg READ alg)
public:
explicit ImageProcessor(QObject *parent = nullptr);
~ImageProcessor();

enum ImageAlg {
GRAY = 0,
BINARIZE,
NEGATIVE,
EMBOSS,
SHARPEN,
SOFTEN,
ALG_COUNT
};

QString sourceFile() const;
ImageAlg alg() const;
void setTempPath(QString tempPath);

signals:
void finished(QString newFile);
void progress(int value);

public slots:
void process(QString file, ImageAlg alg);
void abort(QString file, ImageAlg alg);

private:
ImageProcessorPrivate *m_d;
};

#endif // IMAGEPROCESSOR_H

ImageProcessor.cpp

#include "imageprocessor.h"
#include <QEvent>
#include <QRunnable>
#include <QPointer>
#include <QCoreApplication>
#include <QDir>
#include <QThreadPool>
#include <QDebug>

//将 void ##(QString sourceFile, QString destFile) 函数,声明为 *AlgFunction
//typedef 返回类型(*新类型)(参数表)
typedef void (*AlgFunction)(QString sourceFile, QString destFile);

class AlgRunnable;

class ExcutedEvent : public QEvent
{
public:
ExcutedEvent(AlgRunnable *r) :
QEvent(evType()),
m_runnable(r)
{

}
AlgRunnable *m_runnable;
static QEvent::Type evType()
{
if (s_evType == QEvent::None) {
s_evType = (QEvent::Type)registerEventType();
}
return s_evType;
}

private:
static QEvent::Type s_evType;
};

QEvent::Type ExcutedEvent::s_evType = QEvent::None;

//定义函数原型
static void gray(QString sourceFile, QString destFile);
static void binarize(QString sourceFile, QString destFile);
static void negative(QString sourceFile, QString destFile);
static void emboss(QString sourceFile, QString destFile);
static void sharpen(QString sourceFile, QString destFile);
static void soften(QString sourceFile, QString destFile);

//函数数组的申明方式
static AlgFunction g_functions[ImageProcessor::ALG_COUNT] = {
gray,
binarize,
negative,
emboss,
sharpen,
soften
};

class AlgRunnable : public QRunnable
{
public:
AlgRunnable(QString sourceFile, QString destFile, ImageProcessor::ImageAlg alg, QObject *observer) :
m_observer(observer),
m_sourceFilePath (sourceFile),
m_destFilePath(destFile),
m_alg(alg)
{

}
void run()
{
//执行图像算法
g_functions[m_alg](m_sourceFilePath, m_destFilePath);
//执行图形处理完毕后,发送自定义事件给 ImageProcessor
QCoreApplication::postEvent(m_observer, new ExcutedEvent(this));
}

QPointer<QObject> m_observer; //事件接收者
QString m_sourceFilePath;
QString m_destFilePath;
ImageProcessor::ImageAlg m_alg;
};

class ImageProcessorPrivate : public QObject
{
public:
ImageProcessorPrivate(ImageProcessor *processor) :
QObject(processor),
m_processor(processor),
m_tempPath(QDir::currentPath())
{
ExcutedEvent::evType();
}
~ImageProcessorPrivate()
{

}

bool event(QEvent *event)
{
//当接收到自定义事件,表明图形处理已经完毕,发送 finished() 信号
if (event->type() == ExcutedEvent::evType()) {
ExcutedEvent *ee = (ExcutedEvent*)event;
if (m_runnables.contains(ee->m_runnable)) {
m_notifiedAlg = ee->m_runnable->m_alg;
m_notifiedSourceFile = ee->m_runnable->m_sourceFilePath;
emit m_processor->finished(ee->m_runnable->m_destFilePath);
m_runnables.removeOne(ee->m_runnable);
}
delete ee->m_runnable;
return true;
}
return QObject::event(event);
}

void process(QString sourceFile, ImageProcessor::ImageAlg alg)
{
QFileInfo fi(sourceFile);
QString destFile = QString("%1/%2_%3").arg(m_tempPath).arg((int)alg).arg(fi.fileName());
AlgRunnable *r = new AlgRunnable(sourceFile, destFile, alg, this);
m_runnables.append(r);
r->setAutoDelete(false); //将自动删除设置为 false
//用线程池,执行线程
QThreadPool::globalInstance()->start(r);
}


ImageProcessor *m_processor;
QList<AlgRunnable*> m_runnables;
QString m_notifiedSourceFile;
ImageProcessor::ImageAlg m_notifiedAlg;
QString m_tempPath;
};

ImageProcessor::ImageProcessor(QObject *parent) :
QObject(parent),
m_d(new ImageProcessorPrivate(this))
{

}

ImageProcessor::~ImageProcessor()
{
delete m_d;
}

QString ImageProcessor::sourceFile() const
{
return m_d->m_notifiedSourceFile;
}

ImageProcessor::ImageAlg ImageProcessor::alg() const
{
return m_d->m_notifiedAlg;
}

void ImageProcessor::setTempPath(QString tempPath)
{
m_d->m_tempPath = tempPath;
}

void ImageProcessor::process(QString file, ImageProcessor::ImageAlg alg)
{
m_d->process(file, alg);
}

void ImageProcessor::abort(QString file, ImageProcessor::ImageAlg alg)
{
int size = m_d->m_runnables.size();
AlgRunnable *r;
for (int i=0; i<size; i++) {
r = m_d->m_runnables.at(i);
if (r->m_sourceFilePath == file && r->m_alg == alg) {
m_d->m_runnables.removeAt(i);
break;
}
}
}

void gray(QString sourceFile, QString destFile) {
Q_UNUSED(sourceFile);
Q_UNUSED(destFile);
qDebug() << "灰度";
}
void binarize(QString sourceFile, QString destFile)
{
Q_UNUSED(sourceFile);
Q_UNUSED(destFile);
qDebug() << "黑白";
}
void negative(QString sourceFile, QString destFile)
{
Q_UNUSED(sourceFile);
Q_UNUSED(destFile);
qDebug() << "底片";
}
void emboss(QString sourceFile, QString destFile)
{
Q_UNUSED(sourceFile);
Q_UNUSED(destFile);
qDebug() << "浮雕";
}
void sharpen(QString sourceFile, QString destFile)
{
Q_UNUSED(sourceFile);
Q_UNUSED(destFile);
qDebug() << "锐化";
}
void soften(QString sourceFile, QString destFile)
{
Q_UNUSED(sourceFile);
Q_UNUSED(destFile);
qDebug() << "柔化";
}


举报

相关推荐

0 条评论