Qt 之C++发送图片到Qml显示,踏坑

  • Post author:
  • Post category:其他




项目背景

c++实现逻辑,qml实现内容展示,是qt的未来主流,这次实现的是c++拿到的图片,qml来是显示。

c++的图片是从摄像头获取,然后经过拼接和ocr,来实现实时显示扫描过程。



动态图片的展示

第一步重写

QQuickImageProvider



首先定义一个类并继承于QQuickImageProvider,然后重新实现接口requestPixmap,如果需要传入QImage图片的话就重写requestImage接口

#include <QObject>
#include <QQuickItem>
#include <QQuickImageProvider>
#include <QImage>
class ImageProvider : public QQuickImageProvider
{
public:
    explicit ImageProvider(QObject *parent = nullptr);

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);

    QImage img;
};
ImageProvider::ImageProvider(QObject *parent)  : QQuickImageProvider(QQuickImageProvider::Image)
{
}

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    return this->img;
}

QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
    return QPixmap::fromImage(this->img);
}

第二步 ,注册到qml

void OcrSingleton::registerImageProvider(QQmlEngine *engine)
{
    engine->addImageProvider(QLatin1String("OcrImage"), m_pImageProvider);
    qDebug() << "registerImageProvider";
}

第三步,在处理图片的类中,发送信号通知qml

void OcrSingleton::getOcrImage(const QImage &img)
{
    if(!img.isNull())
    {
        m_pImageProvider->img = img.copy(img.rect());
        emit callQmlRefreshImage();
    }
}
Image{
        id:img
        source: imgsource
        cache:false
        asynchronous: false
        fillMode: Image.PreserveAspectFit
        anchors.left: parent.left
        anchors.top: parent.top
        property bool counter: false
        function reload() {
            counter = !counter
            source = "image://OcrImage?id=" + counter
        }

        Connections{
            target: ocrManager
            onCallQmlRefreshImage:{
                img.reload()
            }
        }
    }



避坑



图片不动态刷新

注意设置Image 的 cache属性是 false

解决方法 1:

function reload() {
            counter = !counter
            source = "image://OcrImage?id=" + counter
        }

        Connections{
            target: ocrManager
            onCallQmlRefreshImage:{
                img.reload()
            }
        }

解决方法 2:

先将image的source 置空,再赋值

  Connections{
            target: ocrManager
            onCallQmlRefreshImage:{
                img.sourec = ""
                img.source ="image://OcrImage"
            }
        }



图片刷新过快的话,出现花屏

这就要考虑到图片是如何拿到的,比如下面两段代码,注意看其中区别

代码段1:

void OcrSingleton::getOcrImage(const QImage &img)
{
    if(!img.isNull())
    {
        m_pImageProvider->img = img;
        emit callQmlRefreshImage();
    }
}

代码段2:

void OcrSingleton::getOcrImage(const QImage &img)
{
    if(!img.isNull())
    {
        m_pImageProvider->img = img.copy(img.rect());
        emit callQmlRefreshImage();
    }
}

明白否?其实就涉及到了图片的深拷贝和浅拷贝问题,常用拷贝赋值的方式如下:

// 浅拷贝

QImage(uchar * data, int width, int height, Format format)

// 浅拷贝

QImage(const uchar * data, int width, int height, Format format)

// 浅拷贝

QImage(uchar * data, int width, int height, int bytesPerLine, Format format)

// 浅拷贝

QImage(const uchar * data, int width, int height, int bytesPerLine, Format format)

// 深拷贝

QImage QImage::copy(const QRect & rectangle = QRect()) const

// 浅拷贝

QImage QImage::rgbSwapped() const

//浅拷贝

QImage &QImage::operator=(const QImage &image)

改成深拷贝后,完美解决刷新花屏问题



版权声明:本文为u011942101原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。