使用来自模型的图像提供者公开多个QImage

时间:2018-07-17 13:18:50

标签: c++ qt qml

我正在尝试在QML中显示QImage,可能与Image一起显示。目前,我发现了QQuickImageProvider之类的东西,我实现并尝试使用它,但没有成功。

我有QList个自己的对象(Item),这些对象通过QAbstractListModel的子类传递给QSortFilterProxyModel的子类,即{{1 }}。 QQuickView中的每个Item都包含QList作为属性。我试图将QImage属性更改为QImage,但是无法为每个ImageProviderQQuickView->engine添加图像提供程序。

我尝试使用ItemImageProvider公开为Item属性,但这与直接引用Q_PROPERTY的结果相同:QImage

Item.h

Unable to assign QImage to QUrl

ImageProvider.h

#include <QObject>
#include <QImage>
#include "ImageProvider.h"

class Item : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QImage getItemPhoto READ getItemPhoto WRITE setItemPhoto NOTIFY photoChanged)

public:
    // ---- PUBLIC METHODS ----
    //! Sets up unique ID for Item
    explicit Item();

    //! Returns image source path
    QImage getItemPhoto() const { return photo_; }

    //! Sets source path for the image of the Item
    void setItemPhoto(const QImage &imageSource);

signals:
    // ---- SIGNALS ----

    photoChanged();

private:
    // ---- PRIVATE METHODS ----
    //! Set id of Item
    void setId(const int &ID);

private:
    // ---- PRIVATE ATTRIBUTES ---

    QImage photo_;

    QImage heatMap_;
};

ImageProvider.cpp

#include <QObject>
#include <QImage>
#include <QQuickImageProvider>

class ImageProvider : public QObject, QQuickImageProvider
{
    Q_OBJECT
public:
    ImageProvider();

    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);

public slots:
    void setPhoto(const QImage &photo);

signals:
    void photoChanged();

private:
    QImage photo_;
};

Main.qml

#include "ImageProvider.h"

ImageProvider::ImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
{
    this->blockSignals(false);
}

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    Q_UNUSED(id)
    QImage res = this->photo_;

    if(res.isNull())
        return QImage();

    if(size)
    {
        *size = res.size();
    }

    if(requestedSize.width() > 0 && requestedSize.height() > 0)
        res = res.scaled(requestedSize.width(), requestedSize.height(), Qt::KeepAspectRatio); //TODO

    return res;
}

void ImageProvider::setPhoto(const QImage &photo)
{
    if(photo_ != photo)
    {
        photo_ = photo;
        emit photoChanged();
    }
}

正如我所说,我尝试添加GridView { //.... model:filterModel delegate: Image { id: item //.... source: item.getItemPhoto //item is role name for Item } } 而不是ImageProvider。但是,我不知道如何将它们显示为QImage

有人知道问题出在哪里吗?

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

您必须将某些ID与图像相关联,并将该ID传递给QQuickImageProvider,在requestImage方法中,您必须使用该ID获取模型的图像。

为此,您必须创建另一个角色,在此示例中,调用与该值的属性关联的uuid。

item.h

#ifndef ITEM_H
#define ITEM_H

#include <QImage>
#include <QObject>
#include <QUuid>

class Item : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QImage photo READ photo WRITE setPhoto NOTIFY photoChanged)
    Q_PROPERTY(QUuid uuid READ uuid NOTIFY uuidChanged) // <---id
public:
    using QObject::QObject;

    QImage photo() const {
        return mPhoto;
    }
    void setPhoto(const QImage &photo){
        mPhoto = photo;
        emit  photoChanged();
        mUuid = QUuid::createUuid();
        emit uuidChanged();
    }
    QUuid uuid() const {
        return mUuid;
    }
signals:
    void photoChanged();
    void uuidChanged();
private:
    QImage mPhoto;
    QUuid mUuid;
};

#endif // ITEM_H

itemmodel.h

QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
    if (!index.isValid())
        return QVariant();
     Item *item =  mItems[index.row()];
    if(role == Qt::UserRole){
        return QVariant::fromValue(item);
    }
    else if(role == Qt::UserRole+1){
        return QVariant::fromValue(item->uuid());
    }
    return QVariant();
}

QHash<int, QByteArray> roleNames() const{
    QHash<int, QByteArray> roles;
    roles[Qt::UserRole] = "item";
    roles[Qt::UserRole+1] = "uuid";
    return roles;
}

modelimageprovider.h

#ifndef MODELIMAGEPROVIDER_H
#define MODELIMAGEPROVIDER_H

#include "item.h"

#include <QAbstractListModel>
#include <QQuickImageProvider>
#include <QUuid>

class ModelImageProvider : public QQuickImageProvider
{
public:
    explicit ModelImageProvider(QAbstractItemModel *model)
        :QQuickImageProvider(QQuickImageProvider::Image)
    {
        mModel = model;
    }
    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize){
        Q_UNUSED(requestedSize)
        Q_UNUSED(size)
        // search item
        QUuid uuid(QByteArray::fromPercentEncoding(id.toLatin1()));
        QModelIndexList indexes = mModel->match(
                    mModel->index(0, 0),
                    Qt::UserRole+1,
                    QVariant::fromValue(uuid),
                    1,
                    Qt::MatchRecursive);
        if(indexes.size() > 0){
            Item *it = qvariant_cast<Item *>(indexes[0].data(Qt::UserRole));
            if(it)
                return it->photo();
        }
        return QImage();
    }
private:
    QAbstractItemModel *mModel;
};

#endif // MODELIMAGEPROVIDER_H

main.cpp

...
ModelImageProvider *provider = new ModelImageProvider(manager.filterModel());
QQmlApplicationEngine engine;
engine.addImageProvider("model", provider);
engine.rootContext()->setContextProperty("manager", &manager);
...

main.qml

...
delegate:
    Image {
    width: 100
    height: 100
    source: "image://model/"+item.uuid
}
...

完整的示例可以在下面的link中找到。

答案 1 :(得分:0)

拍摄所有图像,并使其通过一个ImageProvider可访问。

在QML中的用法如下:

Image { source: "image://myimageprovider/image05.png" }

要链接URL中使用的“ myimageprovider”字符串,必须按以下方式注册提供程序:

QQmlEngine::addImageProvider("myimageprovider", imageProvider);

您的图像提供程序具有成员功能:

virtual QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize);

Qt将URL中的“ image05.png”字符串作为该const QString &id参数传递。