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的圖片要怎麼辦呢?接著看
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()
}
}