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

该代码示例展示了如何在Qt环境中通过自定义事件实现跨线程通信。一个名为`AlgRunnable`的类用于在子线程中执行图像处理任务,完成后发送`ExcutedEvent`事件到主线程。主线程中的`ImageProcessorPrivate`类监听此事件,接收到后触发相应处理,如发送`finished()`信号。整个过程实现了异步处理和线程间的通信。
摘要由CSDN通过智能技术生成

一、概况

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() << "柔化";
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值