qt中c++获取图片qml实时显示的方式1——继承QQuickPaintedItem

通过c++ opencv获取rtsp视频流,或者视频源,在qml上进行实时视频显示。

一、在QML中通过QQuickPaintedItem动态加载图片

在QML中,可以使用QQuickPaintedItem来创建自定义的可绘制项。通过继承QQuickPaintedItem类,我们可以在QML中动态加载图片并进行绘制。在本篇博客中,我们将学习如何使用QQuickPaintedItem加载并绘制图片。

1. opecv 获取视频流图片

.pro文件中引入opencv

#windows
INCLUDEPATH +=D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\include
              D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\include\opencv
              D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\include\opencv2


LIBS +=D:\soft\opencv3.4.0\OpenCV-MinGW-Build-OpenCV-3.4.5\x86\mingw\bin\libopencv_*.dll

创建一个线程类myThread用于获取图片
myThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include "QThread"
#include <QTimer>
#include <QImage>
#include <QMutex>

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>

#include<QtNetwork/QNetworkRequest>
#include<QtNetwork/QNetworkReply>
#include<QtNetwork/QNetworkAccessManager>

class myThread : public QThread
{
    
    
    Q_OBJECT

public:
    explicit myThread(QObject *parent = nullptr);
    myThread(QString url);

protected:
    void run() override;


private:

    cv::VideoCapture video;         // 视频抓取
    cv::Mat src_frame;              // mat类用于存储矩阵类型数据,这里用来存储图像
    QString rtsp;                   // rtsp地址
    bool isStop=false;              // 线程是否运行
    QImage image;

    QNetworkAccessManager * manager;


signals:

    void sendArray(QImage qimg); // 发送图片的信号
    void sendImg(QImage qimg);         // 发送空白图片

public slots:

    void getFrame();            // 获取图像
    void closeFrame();          // 关闭画面
    void closeThread();         // 关闭线程
};

#endif // MYTHREAD_H

myThread.cpp

#include "mythread.h"
#include "QDebug"


myThread::myThread(QObject *parent) : QThread(parent)
{
    
    

    manager=new QNetworkAccessManager(this);
}

myThread::myThread(QString url)
{
    
    
    rtsp=url;

}

void myThread::run()
{
    
    

    qDebug() << "线程开始执行:"<< QThread::currentThread()<<rtsp;
    //  rtsp读取网络视频
    video=cv::VideoCapture(rtsp.toStdString());
    if(video.isOpened())
    {
    
    
        while (!isStop) {
    
    
            getFrame();
            msleep(25);
        }
        if(isStop){
    
    
            closeFrame();
            isStop=false;
        }
    }
}

// 关闭线程
void myThread::closeThread(){
    
    

    isStop=true;
    qDebug() << __FUNCTION__;
}

// 关闭画面
void myThread::closeFrame(){
    
    
    qDebug() << __FUNCTION__;
    emit sendImg(QImage(":/Image/Button/013.png"));
}

// 图像处理
void myThread::getFrame()
{
    
    

    video>>src_frame; //从视频取帧
    // mat to qimage
    if(src_frame.rows>0 && src_frame.cols>0){
    
    
        if(src_frame.channels() == 3) {
    
    
            // RGB image
            cvtColor(src_frame,src_frame,CV_BGR2RGB);
            image = QImage((const uchar*)(src_frame.data),  //(const unsigned char*)
                           src_frame.cols,src_frame.rows,
                           src_frame.cols*src_frame.channels(),   //new add
                           QImage::Format_RGB888);
        }

        else {
    
    
            // gray image
            image = QImage((const uchar*)(src_frame.data),
                           src_frame.cols,src_frame.rows,
                           src_frame.cols*src_frame.channels(),
                           QImage::Format_Indexed8);
        }

        // 发送信号
        emit sendArray(image);
    }else{
    
    
        qDebug() << __FUNCTION__<<"null";

    }
}



2. 创建自定义绘制项–ShowImage.h

首先,我们需要创建一个自定义的绘制项类。在这个类中,我们将重写QQuickPaintedItempaint方法来实现绘制逻辑。

ShowImage.h

#ifndef SHOWIMAGE_H
#define SHOWIMAGE_H

#include <QObject>
#include <QQuickPaintedItem>
#include <QImage>
#include <QPainter>

#include <mythread.h>

// qml 实时加载图片第一种方式--继承QQuickPaintedItem,自定义绘制
class ShowImage : public QQuickPaintedItem
{
    
    
    Q_OBJECT
public:
    explicit ShowImage(QQuickItem *parent = nullptr);

public slots:
    void updateImage(const QImage &);
    void start_camera(QString rtsp);
    void close_camera();

signals:
    void close_thread();

protected:
    void paint(QPainter *painter);

private:
    QImage m_imageThumb;
    QImage image_null=QImage(":/image/test.png");  // 默认图片
    myThread *m_thread=nullptr;  

};

#endif // SHOWIMAGE_H

3. 实现自定义绘制项

接下来,我们需要实现自定义绘制项的逻辑。
ShowImage.cpp

#include "showimage.h"

ShowImage::ShowImage(QQuickItem *parent)
{
    
    
    //默认图片
    m_imageThumb = image_null;
}

// 更新图片
void ShowImage::updateImage(const QImage &image)
{
    
    
    m_imageThumb = image;
    update();
}
// 开启视频捕获
void ShowImage::start_camera(QString rtsp)
{
    
    
    if(m_thread!=nullptr){
    
    
        close_camera();
    }
    m_thread=new myThread(rtsp);
    connect(m_thread,&myThread::sendArray,this,&ShowImage::updateImage);
    connect(m_thread,&myThread::sendImg,this,&ShowImage::updateImage);
    connect(this,&ShowImage::close_thread,m_thread,&myThread::closeThread);
    m_thread->start();

}
// 关闭视频捕获
void ShowImage::close_camera()
{
    
    
    qDebug() <<__FUNCTION__;
    emit close_thread();
    if(m_thread!=nullptr){
    
    
        m_thread->quit();
        m_thread->wait();
        delete m_thread;
        m_thread=nullptr;
    }
}

// 图片绘制
void ShowImage::paint(QPainter *painter)
{
    
    
    if(!m_imageThumb.isNull()){
    
    
        painter->drawImage(this->boundingRect(), m_imageThumb);
    }else{
    
    
        painter->drawImage(this->boundingRect(), QImage(image_null));
    }
}




4. 在main.cpp中注册自定义绘制类

main.cpp中注册自定义类给qml使用

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <showimage.h>
#include "myimageprovider.h"

int main(int argc, char *argv[])
{
    
    
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    // 获取上下文对象
    QQmlContext *context=engine.rootContext();
    // 注册自定义类
    qmlRegisterType<ShowImage>("ShowImage",1,0,"ShowImage");

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
    
    
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
    
    return app.exec();
}

5. qml中使用自定义绘制类

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0

import ShowImage 1.0  // 导入自定义模块
Window {
    
    
    visible: true
    width: screenW
    height: 480
    title: qsTr("Hello World")

    // 第一种方式--使用自定义模块
    ShowImage{
    
    
        anchors.fill: parent
        id : showimg
        transformOrigin: Item.Center
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
    }

    Button {
    
    
        id:ok
        text: "相机"
        anchors.left: parent.left
        anchors.leftMargin: 20
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 50
        width: parent.width*0.2
        height: 50

        signal start_time_qml()   // 定义信号
        Connections {
    
    			  // 连接信号与槽
            target: ok
            onStart_time_qml: {
    
    
                showimg.start_camera("rtsp://admin:[email protected]/smart265/ch1/main/av_stream")
            }
        }
        onClicked: {
    
    
            ok.start_time_qml()
        }
    }

    Button {
    
    
        id:video
        text: "视频源"
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 50
        width: parent.width*0.2
        height: 50
        x:parent.width*0.32

        signal start_video_qml()
        Connections {
    
    
            target: video
            onStart_video_qml: {
    
    
                showimg.start_camera("H:\\360MoveData\\Users\\Administrator\\Desktop\\11.mp4")
            }
        }
        onClicked: {
    
    
            video.start_video_qml()
        }
    }

    Button {
    
    
        id:clear
        text: "关闭"
        anchors.right: parent.right
        anchors.rightMargin: 20
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 50
        width: parent.width*0.2
        height: 50
        x:parent.width*0.62

        signal clear_time_qml()
        Connections {
    
    
            target: clear
            onClear_time_qml: {
    
    
                showimg.close_camera()
            }
        }
        onClicked: {
    
    
            clear.clear_time_qml()
        }
    }
}

6. 运行程序

现在,你可以运行应用程序并点击对应按钮来动态加载并显示图片。当你点击按钮时,ShowImage将使用updateImage方法加载指定路径的图片,并将其绘制到界面上。

在这里插入图片描述

扫描二维码关注公众号,回复: 16098053 查看本文章

以播放视频为例:

qml 实时显示

这就是在QML中通过QQuickPaintedItem动态加载图片的基本步骤。你可以根据需要进一步定制自定义绘制项的功能和外观。

希望本篇博客对你有所帮助!如果你有任何问题,请随时提问。

源代码

猜你喜欢

转载自blog.csdn.net/ljn1046016768/article/details/131332297