概述
在QML中,图片加载提供了三种方式,分别如下:
- 加载资源的方式:qrc://图片路径
- 加载本地问价的方式:file:///图片路径
- 使用图片提供者:image://图片提供者
本章说的是第三种方式,即使用图片提供者的方式在QML中加载图片。
QQuickImageProvider简介:提供二进制加载图片或pixmap in qml
实现
话不多说,直接上代码(ps:自己做的小demo)
// !!!!! ImageProvider.h
#include <QQuickImageProvider>
//子类化QQuickImageProvider
class ImageProvider : public QQuickImageProvider
{
public:
explicit ImageProvider();
// QQuickImageProvider interface (重写一个方法,也可以重新requestPixmap(),用于qml找图片提供者请求图片的格式)
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
public:
QImage m_img;
};
// !!!!!ImageProvider.cpp
#include "imageprovider.h"
ImageProvider::ImageProvider():
QQuickImageProvider(QQuickImageProvider::Image) //必须初始化基类
{
}
QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
return this->m_img;
}
由于我是自己测试的,请求的图片来自本地,所以增加了一个工具类Client
// !!!! Client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QObject>
#include "imageprovider.h"
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(QObject *parent = nullptr);
~Client();
Q_INVOKABLE void loadImage(); //Q_INVOKABLE允许这个方法在QML中被调用
signals:
public:
ImageProvider* imgPro; //图片提供者
};
// !!!! Client.cpp
#include "client.h"
#include <QTemporaryFile>
#include <QCoreApplication>
#include <QDir>
#include <QFileDialog>
Client::Client(QObject *parent)
: QObject{parent}
{
imgPro = new ImageProvider;
}
Client::~Client()
{
imgPro->deleteLater();
}
void Client::loadImage()
{
QString fileName = QFileDialog::getOpenFileName(0, tr("Open File"),
"/home",
tr("Images (*.png *.xpm *.jpeg)"));
// qDebug() << fileName;
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly)){
qDebug() << file.errorString();
return;
}
QByteArray arr = file.readAll();
this->imgPro->m_img.loadFromData(arr);
}
// main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "client.h"
#include "imageprovider.h"
#include <QDir>
#include <QQmlContext>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
QQmlApplicationEngine engine;
Client* c = new Client;
engine.addImageProvider(QLatin1String("img"),c->imgPro); //添加图片提供者
engine.rootContext()->setContextProperty("$Client",c); //必须保证Client的实例是唯一的,才能刷新图片
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
// main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Image{
id:img1
// cache: false
width: 70
height: 70
anchors.centerIn: parent
source: "image://img" //由imageProvider提供图片数据,支持QPixmap和QImage
}
Timer{
interval: 5000
repeat: false
running: true
onTriggered: {
$Client.loadImage()
}
}
}
至此,QQuickImageProvider的实现完成了,可以运行看一下效果(运行,打开本地一张图片,可看到图片以图片提供者的方式在QML中被加载)
简单总结一下QQuickImageProvider的使用:
- 子类化QQuickImageProvider,重写requestImage() 或者requestPixmap() ,并给出对应实现。
- 将所需要的数据,提前给图片提供者准备好,方便QML在请求图片的时候,图片提供者能够提供图片数据
- 将图片提供者实例注册进入上下文环境中,使用QQmlEngine::addImageProvider()。
- QML中的Image组件的属性格式为:image://(图片提供者实例),注意:图片提供者实例是必须要有的