前言:
上篇教程就提到了,加入扫码后,程序会变的很卡顿,本教程通过多线程的方式,解决卡顿问题
同时这也可能是本系列教程的最后一篇widget的文档了
本教程是在 Qt5.15.2+Qt6.2.1(widget)+opencv4.5.4实现扫码功能 示例的基础上修改
一、修改处理类
类Tool_Process头文件修改如下
#include "opencv2/opencv.hpp"
#include <QObject>
#include <QImage>
#include <QTimerEvent>
#include <QMutex>
class Tool_Process : public QObject
{
Q_OBJECT
public:
explicit Tool_Process(QObject *parent = nullptr);
~Tool_Process();
//添加待处理的图像
void setImage(const QImage &image);
signals:
//返回已解读的二维码数据
void qrString(const QString string);
//启动定时器
void start();
protected:
//处理定时器事件
void timerEvent(QTimerEvent *event) override;
private:
//二维码解码
void process();
//将QImgae对象转换为cv::Mat
cv::Mat QImage2cvMat(QImage image);
//启动定时器
void onStart();
//保存的图像
QImage m_image;
//定时器Id
int m_timerId = -1;
//互斥量
QMutex m_mutex;
源文件修改的关键代码
以下代码是为类提供一个定时器,定时器会定时执行一次处理函数,处理已保存的图像
Tool_Process::~Tool_Process()
{
if(m_timerId >= 0)
killTimer(m_timerId);
}
/*!
* \brief Tool_Process::onStart 启动定时器
*/
void Tool_Process::onStart()
{
if(m_timerId < 0)
m_timerId = startTimer(200);
}
/*!
* \brief Tool_Process::timerEvent 处理定时器事件
* \param event
*/
void Tool_Process::timerEvent(QTimerEvent *event)
{
if(event->timerId() == m_timerId )
{
process();
return;
}
QObject::timerEvent(event);
}
新添加的处理函数
/*!
* \brief Tool_Process::process 二维码解码
*/
void Tool_Process::process()
{
QImage image;
{
QMutexLocker locker(&m_mutex);
if(m_image.isNull())
return;
image = m_image;
m_image = QImage();
}
cv::QRCodeDetector decoder;
cv::Mat mat,bbox,rect;
mat=QImage2cvMat(image);
if(decoder.detect(mat,bbox)){
qDebug()<<"getQRCode";
std::string result = decoder.decode(mat,bbox);
const QString resultString = QString::fromStdString(result);
qDebug() << "QRdecoder"<<resultString;
if(!resultString.isEmpty())
emit qrString(resultString);
}
}
说明:
1.在程序运行时,主线程调用setImage()函数,不停注入新的图像,但处理类只保留最后一张图像
2.process()运行在新开的线程中,被定时触发,若有图像未处理,就处理掉
二、修改调用方式(使用多线程)
在主程序中,处理类的处理函数初始化修改下,将处理类放在新开的线程序中
以下代码供小伙伴们参考
//初始化处理类
m_tool_Process = new Tool_Process;
QThread *thread = new QThread;
connect(m_tool_Process, &Tool_Process::destroyed, thread, &QThread::quit);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
connect(m_tool_Process, &Tool_Process::qrString,[this](const QString string){
ui->lineEdit_result->setText(string);
});
m_tool_Process->moveToThread(thread);
thread->start();
emit m_tool_Process->start();
修改完成以上代码,就可以运行程序了,以下是笔者的运行结果
可以很明显的感觉到,之前的卡顿感没了
本次教程源码下载
后记:
在Qt中,越来越多的使用qml,在写本教程时,同事曾建议直接使用qml。考虑到不小伙伴对qml不熟悉,笔者坚持先进行widget的例程。
今天因为搬家耽误了太多时间,具体的教程只能明天再写了