一、概况
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() << "柔化";
}