项目背景
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)
改成深拷贝后,完美解决刷新花屏问题