天天看點

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