天天看点

QML之图片动态显示(Image与QQuickImageProvider)

最近,需要在QML上显示来自OPenCV的摄像头视频,因为是视频,即好多好多图片,所以需要QML上动态刷新来自C++的QImage。具体怎么搞我就不再赘述,虽然资料不多,但是CSDN上的一篇博客已经写得十分的清楚。该博客如下:

前言

开发Qt应用时,想把QImage发送到QML端通过Image组件显示出来,这种场景主要用在例如在C++端调用android系统接口截图然后发送到QML端显示,或者C++端QWidget截图然后让QML界面中显示。要想实现该功能,需要用到一个重要的类QQuickImageProvider,这是专门从C++端提供图片到QML显示的。

正文

先来看看Qt的示例

首先定义一个类并继承于QQuickImageProvider,然后重新实现接口requestPixmap,如果需要传入QImage图片的话就重写requestImage接口,原理是一样的,详情查看Qt官方文档。

class ColorImageProvider : public QQuickImageProvider
  {
  public:
      ColorImageProvider()
          : QQuickImageProvider(QQuickImageProvider::Pixmap)
      {
      }

      QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
      {
          int width = 100;
          int height = 50;

          if (size)
              *size = QSize(width, height);
          QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width,
                         requestedSize.height() > 0 ? requestedSize.height() : height);
          pixmap.fill(QColor(id).rgba());

          return pixmap;
      }
  };
           

然后在main函数中添加图片入口,使用addImageProvider函数

int main(int argc, char *argv[])
  {
      ...

      QQuickView view;
      QQmlEngine *engine = view.engine();
      engine->addImageProvider(QLatin1String("colors"), new ColorPixmapProvider);

      ...
  }
           

再在QML端界面上显示

Column {
      Image { source: "image://colors/yellow" }
      Image { source: "image://colors/red" }
  }
           

这里的colors就是main函数中定义的图片文件夹名称,yellow和red相当于id,也就是在requestPixmap中的第一个参数可以拿到这个值。编译运行后,得到如下示意图: 

QML之图片动态显示(Image与QQuickImageProvider)

动态刷新图片

以上是显示一张静态图片,如果是要动态的刷新QML的图片要怎么办呢?接着看

class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider();

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

    QImage img;

};
           
#include "imageprovider.h"

ImageProvider::ImageProvider()
    : 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);
}
           

然后再定义一个类

class ShowImage : public QObject
{
    Q_OBJECT
public:
    explicit ShowImage(QObject *parent = 0);
    ImageProvider *m_pImgProvider;
public slots:
    void setImage(QImage image);
signals:
    void callQmlRefeshImg();
};
           
ShowImage::ShowImage(QObject *parent) :
    QObject(parent)
{
    m_pImgProvider = new ImageProvider();
}
void ShowImage::setImage(QImage image)
{
    m_pImgProvider->img = image;
    emit callQmlRefeshImg();
}
           

然后在main函数中注册

ShowImage *CodeImage = new ShowImage(this);
engine.rootContext()->setContextProperty("CodeImage",CodeImage);
engine.addImageProvider(QLatin1String("CodeImg"), CodeImage->m_pImgProvider);
           

回到QML中调用

Image{
        id:img
        anchors.fill: parent
    }
    Connections{
        target: CodeImage
        onCallQmlRefeshImg:{
            img.source = ""
            img.source = "image://CodeImg"
        }
    }
           

注意,这里刷新图片的时候必须先设置为空img.source = “”,否则无法刷新。 

这样一来,C++端设置新图片后会发送信号,在QML端连接信号然后去图片目录下去取出来刷新当前控件。原理很简单,不再赘述。

--------------------- 博客完结--------------------------------------------

但是!

我按照他们的方法,根本无法正常刷新图片,只能显示第一张!!!

我按照他们的方法,根本无法正常刷新图片,只能显示第一张!!!

我按照他们的方法,根本无法正常刷新图片,只能显示第一张!!!

后来….一段艰辛…..终于解决问题….记录与此,望其他小伙伴不要重蹈覆辙 

其实,后面的版本中(我用的5.8),这样已经不行了,猜测是更新了缓存机制的原因 

如果使用相同的地址去获取图片…那么就直接从缓存里拿,so,无法正常刷新,如果你想正常刷新,可以采取下面这种写法:

Image{
        id:img
        anchors.fill: parent
    }
    Connections{
        target: CodeImage
        onCallQmlRefeshImg:{
            img.source = "image://CodeImg/"+ Math.random()
        }
    }
           

这样,就能正常从C++那边获取QImage了~

原文链接:https://blog.csdn.net/keysking/article/details/78736841