最近,需要在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中的第一個參數可以拿到這個值。編譯運作後,得到如下示意圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICdzFWRoRXdvN1LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX9UkaOpHNXRWNGdVZ2ZFSiZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DMxcTN1QTMzIzMxMDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
動态重新整理圖檔
以上是顯示一張靜态圖檔,如果是要動态的重新整理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