首页 > 其他分享 >Qt结合QThread创建一个QWidget基类,用于方便的在QWidget中执行耗时任务

Qt结合QThread创建一个QWidget基类,用于方便的在QWidget中执行耗时任务

时间:2023-12-01 13:33:06浏览次数:28  
标签:pixmap Qt 耗时 void HandlerThread QWidget 基类 include BaseSceneView

一、概述

  背景:Qt+OpenCV项目改造,之前项目中的OpenCV算法都是在主线程中执行,导致部分操作或者重复点击的时候界面卡顿。现在想对这块进行改造。

      集合QThread和QWidget设计一个QWidget基类用于方便的执行耗时任务并显示执行结果。子类只需要继承这个QWidget基类,只需要重写一个handle方法用于执行耗时任务(在子线程执行),调用execute()方法开启耗时任务的执行即可。

      现成切换全封装到基类中。

  设计需要的类:

    1.Handler.h定义一个handle接口,子类需要实现它。作用是通过继承关系父类调用子类方法

    2.HandlerThread.h/.cpp 继承QThread,并把Handler类传入,在run方法中调用Handler执行耗时操作,执行完成会通过emit updateUI发送信号

    3.BaseSceneView.h/.cpp此类是基类,此类中会导入HandlerThread类,并继承Handler类。此类会捕获HandlerThread的run方法发出的信号,然后通过updateImage更新UI

    4.子类实现BaseSenceView,重写handle方法,如果有耗时任务则放入handle方法即可。耗时任务是通过父类的execute()方法执行的

二、示例代码

  1.Handler.h

#pragma once

#include <QPixmap>
class Handler
{

public:
    virtual QPixmap handle() {
        return NULL;
    }
};

 

  2.HandlerThread.h/.cpp

#pragma once

#include <QThread>
#include <QPixmap>
#include "Handler.h"

class HandlerThread : public QThread
{
    Q_OBJECT

public:
    HandlerThread(QObject* parent, Handler* handler);
    ~HandlerThread();

private:
    Handler* handler;

protected:
    void run();//线程执行体

signals:
    void updateUI(QPixmap pixmap);//发送更新UI的信号

};
#include "HandlerThread.h"

HandlerThread::HandlerThread(QObject* parent, Handler* handler)
    : QThread(parent)
{
    this->handler = handler;
}

void HandlerThread::run() {
    QPixmap pixmap = handler->handle();
    emit updateUI(pixmap);
}

HandlerThread::~HandlerThread()
{

}

 

  3.BaseSenceView.h/.cpp

#pragma once

#include <stdint.h>
#include <QWidget>
#include <QGraphicsScene>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QResizeEvent>
#include <QSize>
#include <QGraphicsView>
#include <QMessageBox>
#include <QMimeData>
#include <QFileInfo>
#include <QStringList>
#include <QGraphicsPixmapItem>
#include <QDebug>
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsPolygonItem>
#include <QSlider>
#include <QDebug>
#include <QPixmap>
#include <QImage>
#include <opencv2/opencv.hpp>
#include "../utils/ImageUtils.h"
#include "HandlerThread.h"

class BaseSceneView : public QWidget,public Handler
{
    Q_OBJECT

public:
    BaseSceneView(QWidget* parent = nullptr);
    ~BaseSceneView();

private:
    HandlerThread* mThread;
    QGraphicsView* view;
    QGraphicsScene scene;
    

protected:
    void dragEnterEvent(QDragEnterEvent* event);
    void dropEvent(QDropEvent* event);
    void resizeEvent(QResizeEvent* event);
    
    
public:
    //调用此方法开始执行耗时任务,此方法必须调用否则耗时任务不执行,
    //此处的耗时任务就是,handle()方法中的代码块
    void execute();//执行耗时任务
    //此方法必须要重写,需要把耗时任务放进去
    virtual QPixmap handle() {
        return NULL;
    }
    

private:
    //向场景中添加Bitmap
    void addPixmap(QPixmap pixmap);
    void addImage(QImage image);
    void addMat(cv::Mat mat);
    //更新UI4
    void updateImage(QPixmap pixmap);

public slots:
    void onHSliderValueChanged(int value);



private:
};
#include "BaseSceneView.h"

BaseSceneView::BaseSceneView(QWidget* parent)
    : QWidget(parent)
{
    this->setAcceptDrops(true);//允许往窗口拖放
    this->setFixedSize(QSize(320, 480));
    view = new QGraphicsView(this);//实例化View
    view->setMouseTracking(true);
    view->setFixedSize(this->size());
    view->setAcceptDrops(false);
    view->setScene(&scene);//给View设置场景
    mThread = new HandlerThread(this, this);//子线程,用于处理耗时任务,处理完成后发送信号
    //接收上面线程执行完成后发出的信号
    connect(mThread, &HandlerThread::updateUI, this, [=](QPixmap pixmap) {
        updateImage(pixmap);
        });
}
void BaseSceneView::dragEnterEvent(QDragEnterEvent* event) {
    QStringList acceptedFileTypes;
    acceptedFileTypes.append("jpeg");
    acceptedFileTypes.append("png");
    acceptedFileTypes.append("bmp");
    acceptedFileTypes.append("jpg");//设置可以接受的文件格式类型
    if (event->mimeData()->hasUrls() && event->mimeData()->urls().count() == 1) {
        QFileInfo file(event->mimeData()->urls().at(0).toLocalFile());
        if (acceptedFileTypes.contains(file.suffix().toLower())) {
            event->acceptProposedAction();
        }
    }
    else {
        QMessageBox::critical(this, "Error", "count not load mulit files");
    }
}

//拖动内容到窗口
void BaseSceneView::dropEvent(QDropEvent* event) {
    scene.clear();
    QFileInfo file(event->mimeData()->urls().at(0).toLocalFile());
}

void BaseSceneView::resizeEvent(QResizeEvent* event) {

}

void BaseSceneView::onHSliderValueChanged(int value) {


}
void BaseSceneView::addPixmap(QPixmap pixmap) {
    scene.clear();
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(pixmap.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    scene.addItem(item);//给场景添加内容
}

void BaseSceneView::addImage(QImage image) {
    scene.clear();
    QPixmap pixmap = QPixmap::fromImage(image);
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(pixmap.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    scene.addItem(item);//给场景添加内容
}

void BaseSceneView::addMat(cv::Mat mat) {
    scene.clear();
    QImage image = ImageUtils::matToQImage(mat);
    QPixmap pixmap = QPixmap::fromImage(image);
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(pixmap.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    scene.addItem(item);//给场景添加内容
}

void BaseSceneView::updateImage(QPixmap pixmap) {
    addPixmap(pixmap);
}


//执行耗时任务(执行耗时任务前需要调用)
void BaseSceneView::execute() {
    mThread->start();
}

BaseSceneView::~BaseSceneView()
{
}

 

标签:pixmap,Qt,耗时,void,HandlerThread,QWidget,基类,include,BaseSceneView
From: https://www.cnblogs.com/tony-yang-flutter/p/17869505.html

相关文章

  • 用matplot和seaborn作图,出现This application failed to start because not Qt platfo
    用matplotlib和seaborn作图,出现这样的弹窗: 尝试过增加环境变量的方法没有解决。使用了一种临时的解决方法:importmatplotlibmatplotlib.use('TKAgg')如果不需要图形化界面,只需要运行后的参数可以使用:importmatplotlibmatplotlib.use('Agg') ......
  • centos7-MQTT Server搭建(apache-apollo)搭建和配置
    #############################安装apache-apollo###################################################官方的安装文档:http://activemq.apache.org/apollo/documentation/getting-started.htmlhttp://www.apache.org/dyn/closer.cgi?path=activemq/activemq-apollo/1.7.1/apach......
  • Qt应用开发--国产工业开发板全志T113-i的部署教程
    Qt在工业上的使用场景包括工业自动化、嵌入式系统、汽车行业、航空航天、医疗设备、制造业和物联网应用。Qt被用来开发工业设备的用户界面、控制系统、嵌入式应用和其他工业应用,因其跨平台性和丰富的功能而备受青睐。Qt能够为工业领域带来什么好处:-Qt提供了强大的图形引擎,使开发......
  • Qt主线程和子线程协作更新UI
    一、概述现有一个需求:Qt+OpenCV执行角点检测。使用Qt当做UI界面进行角点检测。我们知道像角点检测这种算法需要大量的计算,是比较耗时的一个操作。如果把计算+UI显示全放入主线程中计算,那么UI界面有可能就会卡主,进而出现应用程序无响应的情况。要求:使......
  • Windows10+Qt+OpenCV出现“ACCESS_MASK”: 不明确的符号
    一、概述背景:Qt+OpenCV一模一样的代码在Mac上运行是正常的,在Windows10上运行就会报一下错误。“ACCESS_MASK”:不明确的符号二、原因及解决方案原因:OpenCV4.5.3的命名空间usingnamespacecv;和windows中的ACCESS_MASK定义冲突,在windows.h头文件中。......
  • 使用emqttd时执行emqttd console时无反应或者报错Node undefined not responding to p
    1.无反应:  2.报错:Nodeundefinednotrespondingtopings. 解决办法:路径不能有空格,最好用存英文的路径。......
  • Qt之QSqlDatabase的用法
    一、常用函数的介绍QSqlDatabase类是Qt中用于管理数据库连接的类。它提供了创建、配置、打开和关闭数据库连接的方法。1.addDatabase函数staticQSqlDatabaseaddDatabase(constQString&type,constQString&connectionName=QLatin1String(defaultConnection));该函......
  • Qt 给QCheckBox增加样式
    一、概述做一个好看的QCheckBox二、示例1.样式QCheckBox{spacing:5px;}QCheckBox::indicator{width:24px;height:24px;}QCheckBox::indicator:unchecked{image:url(:images/icon_checked.png);}QCheckBox::indicator:unchecked:......
  • MQTT vs. HTTP: which one is the best for IoT?
    MQTTvs.HTTP:whichoneisthebestforIoT? BeginnersGuideToTheMQTTProtocolhttp://www.steves-internet-guide.com/mqtt/翻译搜索复制......
  • Qt给QRadioButton设置自定义样式
    一、概述做一个好看的QRadioButton。可以选中,取消选中。二、代码示例1.样式QRadioButton::indicator::unchecked{border-image:url(images/user_protocol_uncheck.webp);}QRadioButton::indicator::checked{border-image:url(images/user_protocol_......