QQuickImageProvider提供了一个可以供我们对QPixmap及多线程的Image请求。这个请求的文件甚至可以在网络上。它的好处是:
- 在Image中装载一个QPixmap或QImage而不是一个具体的图像文件
- 在另外一个thread异步装载图片
通过访问一个图片可以通过如下的方式:
Column {
Image { source: "image://colors/yellow" }
Image { source: "image://colors/red" }
}
显然,这里的yellow和red不是文件名。它的提供依赖于在QQuickImageProvider中的requestImage的具体实现。
下面我们来通过一个具体的例程来介绍如何使用QQuickImageProvider来从网路上请求一个我们需要的图像。
myimageprovider.h
#ifndef MYIMAGEPROVIDER_H
#define MYIMAGEPROVIDER_H
#include <QQuickImageProvider>
class QNetworkAccessManager;
class MyImageProvider : public QQuickImageProvider
{
public:
MyImageProvider(ImageType type, Flags flags = 0);
~MyImageProvider();
QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize);
protected:
QNetworkAccessManager *manager;
};
#endif // MYIMAGEPROVIDER_H
myimageprovider.cpp
#include "myimageprovider.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
MyImageProvider::MyImageProvider(ImageType type, Flags flags) :
QQuickImageProvider(type,flags)
{
manager = new QNetworkAccessManager;
}
MyImageProvider::~MyImageProvider()
{
delete manager;
}
QImage MyImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
qDebug() << "id: " << id;
qDebug() << "reequestedSize: " << requestedSize.width() + " " + requestedSize.height();
QUrl url("http://lorempixel.com/" + id);
QNetworkReply* reply = manager->get(QNetworkRequest(url));
QEventLoop eventLoop;
QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec();
if (reply->error() != QNetworkReply::NoError)
return QImage();
QImage image = QImage::fromData(reply->readAll());
size->setWidth(image.width());
size->setHeight(image.height());
return image;
}
QQuickImageProvider(ImageType type, Flags flags = 0)
virtual ~QQuickImageProvider()
Flags flags() const
ImageType imageType() const
virtual QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize)
virtual QPixmap requestPixmap(const QString & id, QSize * size, const QSize & requestedSize)
virtual QQuickTextureFactory * requestTexture(const QString & id, QSize * size, const QSize & requestedSize)
Image { source: "image://myprovider/500/500/" }
显然我们看到的source不是一个具体的文件。并且,它的source是以“image://”开始的。
我们在我们的main.cpp中做如下的实现:
#include "myimageprovider.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
QQmlEngine *engine = view.engine();
MyImageProvider *imageProvider = new MyImageProvider(QQmlImageProviderBase::Image);
engine->addImageProvider("myprovider", imageProvider );
view.setSource(QUrl(QStringLiteral("qrc:///Main.qml")));
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.show();
return app.exec();
}
我们的main.qml文件如下:
main.qml
import QtQuick 2.0
import Ubuntu.Components 1.1
/*!
\brief MainView with a Label and Button elements.
*/
MainView {
// objectName for functional testing purposes (autopilot-qt5)
objectName: "mainView"
// Note! applicationName needs to match the "name" field of the click manifest
applicationName: "imageprovider.liu-xiao-guo"
/*
This property enables the application to change orientation
when the device is rotated. The default is false.
*/
//automaticOrientation: true
// Removes the old toolbar and enables new features of the new header.
useDeprecatedToolbar: false
width: units.gu(60)
height: units.gu(85)
Page {
title: i18n.tr("imageprovider")
Image {
id: img
anchors.centerIn: parent
source: "image://myprovider/500/500/"
anchors.fill: parent
onStatusChanged: {
if(status == Image.Ready)
indicator.running = false;
}
ActivityIndicator {
id: indicator
anchors.centerIn: parent
running: false
}
MouseArea {
anchors.fill: parent
onClicked: {
indicator.running = true;
img.source = "image://myprovider/500/500/?seed=" + Math.random(1000)
}
}
}
}
}