QQuickImageProvider在QML设计中的应用

QQuickImageProvider提供了一个可以供我们对QPixmap及多线程的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;
}

上面我们从网路地址“http://lorempixel.com/”取得文件,并转化为一个QImage。QQuickImageProvider要求我们必须实现如下的一个virtual方法。

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)

我们可以在QML中通过如下的方式来访问一个图片:

 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();
}

注意这里的“myprovider”和我们上面的Image中访问的对应起来。

我们的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)
                }
            }
        }
    }
}

我们在点击图片时,它会自动地随机地从网站取得下一个图片,并显示出来:

 

整个项目的源码在:git clone https://gitcafe.com/ubuntu/imageprovider.git

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-06 03:45:27

QQuickImageProvider在QML设计中的应用的相关文章

如何在QML应用中使用Javascript解析JSON

很多QML应需要访问web services.我们可以通过Javascript的方法来解析得到我们所需要的JSON数据,并把它们展示出来.在今天的例子中,我们将展示如何实现它? 我们可以创建一个最基本的"QML App with Simple UI (qmlproject)",并取名我们的应用为"baidutranslator".我们将使用的API为: http://openapi.baidu.com/public/2.0/bmt/translate?client_

怎样在QML应用中调用系统设置中的页面来设置我们的系统

我们在QML应用中有时须要调用系统设置(system settings)来完毕我们的一些设置.比方,我们在使用GPS来定位时,可能GPS并没有打开,假设在我们的应用中直接打开系统中的GPS设置页面,这样我们就能够直接打开系统的GPS而不用单独设计一个页面.我们能够通过使用URL dispatcher的方法来打开另外一个应用.在先前的我们的文章中,我们已经讲述了非常多关于URL dispatcher方面的东西: 怎么在Ubuntu手机上发送短信及拨打电话 使用URL dispatcher的范例 关

如何在QML应用中实现一个Splash画面

在QML应用中,我们经常要用到一个SplashScreen的画面来渲染我们的应用.那么我们怎么在自己的应用中做一个Splash Screen呢? 首先我们来设计一个自己的SplashScreen的QML模块: SplashScreen.qml import QtQuick 2.0 Item { id: splash anchors.fill: parent property int timeoutInterval: 2000 signal timeout Image { id: splashIm

如何在QML应用中读写文件

我们知道,在QML应用中,有时我们需要来读写一些文件,但是在我们的QML语言中并没有相应的API接口来供我们做(虽然有API接口来存储设置文件等).那么我们怎么来做这个事情呢?我们可以通过Qt C++的方法来实现这个功能. 1)创建一个简单的模版应用 我们使用Ubuntu SDK的模版来创建一个最简单的应用:      我们选择"QML App with C++ plugin"模版来做我们的应用. 2)添加文件读写的文件到项目中 我们添加如下的C++ "FileIO类到我们的

如何在QML应用中启动Scope

在这篇文章中,我们将介绍如何在QML应用中调用Scope,并把搜索的关键词传进去.这对有些QML应用需要用到Scope的情况非常有用.更多关于url-dispatcher的知识,请在文章"使用URL dispatcher的范例"看到. Scope ID 首先我们来讲一下什么是Scope ID.我们打开我们创建的任何一个Scope的manifest.json文件: { "architecture": "@[email protected]", &q

如何在QML应用中得到一个Item的所有属性,信号及方法

Item是QML语言中最基本的元素.有时为了方便,我们可以列出它里面的所有的属性,信号及方法.我们可以通过这个方法来修改我们的属性等.在QML语言中,所有的可视的控件都是继承于Item的. 下面我们来通过一个例子来展示如何这么做.我们可以设计一个简单的QML应用如下: import QtQuick 2.0 import Ubuntu.Components 1.1 /*! \brief MainView with a Label and Button elements. */ MainView {

如何在QML应用中调用系统设置中的页面来设置我们的系统

我们在QML应用中有时需要调用系统设置(system settings)来完成我们的一些设置.比如,我们在使用GPS来定位时,可能GPS并没有打开,如果在我们的应用中直接打开系统中的GPS设置页面,这样我们就可以直接打开系统的GPS而不用单独设计一个页面.我们可以通过使用URL dispatcher的方法来打开另外一个应用.在先前的我们的文章中,我们已经讲述了很多关于URL dispatcher方面的东西: 怎么在Ubuntu手机上发送短信及拨打电话 使用URL dispatcher的范例 关于

在QML应用中如何实现drag and drop功能

在这篇文章中,我们将展示如何在QML应用中实现drag and drop的功能.更多的阅读可以参照Qt SDK. 在这里,我们首先设计一个DropTile.qml DropTile.qml import QtQuick 2.0 DropArea { id: dragTarget property string colorKey property alias dropProxy: dragTarget width: mainpage.width/4 - units.gu(1) height: wi

在QML应用中使用Canvas来画图

我们知道画图应用设计中比较重要,虽然QML有很多可以帮我们渲染的控件.我们可以在QML应用中使用Canvas来画我们所需要的图.比如我们可以利用Canvas来画股票的曲线.Canvas中的画图的API和HTTML5中的API是一样的.事实上,我们很容易使用这个API来把很多的HTML5的应用移植到Qt平台中. ColorSquare.qml import QtQuick 2.0 Rectangle { id: root width: 48; height: 48 color: "green&qu