使用 QQuickImageProvider 的正确方法是啥?

Posted

技术标签:

【中文标题】使用 QQuickImageProvider 的正确方法是啥?【英文标题】:What is the right way to use QQuickImageProvider?使用 QQuickImageProvider 的正确方法是什么? 【发布时间】:2015-05-15 18:58:39 【问题描述】:

我需要动态选择 qpixmaps 以显示在 QML Image 项目中。应该从源 qpixmap 中裁剪 qpixmaps,我将从 QML 文件中设置它。我希望它们在 QML 的第一次需求时被 C++ 代码裁剪,并被缓存以备将来使用。对于动态图像操作,它应该从 QQuickImageProvider 派生我自己的类并将其加载到 QML 应用程序引擎。但是我怎样才能控制源 qpixmap 呢?通过财产?如果是,那么我的自定义提供程序必须从 QObject 派生,并且它的实例应该在 QML 中声明,不是吗?但它怎么能被引擎加载呢?我觉得这种实现方式是错误的,但是哪一种是正确的呢?

UPD:好的,我有课:

class MyQuickImageProvider : public QQuickImageProvider 
public:
    ...
    // This method should set the source image path
    void setPath ( QUrl path );
    // Overriden method of base class; should return cropped image
    virtual QPixmap requestPixmap ( const QString &id, QSize *size, const QSize &requestedSize );
    ...

在 main.cpp 中它被加载为:

QQmlApplicationEngine engine;
...
engine.addImageProvider("my_quick_image_provider", new MyQuickImageProvider(QQmlImageProviderBase::Image));

我想通过 QML 更改源图像路径。如何使 setPath 方法可供它访问?显而易见的方法是将方法声明为 Q_INVOKABLE(并从 QObject 和 qmlRegisterType 派生 MyQuickImageProvider),但是我应该在 QML 源中声明我的类的实例:

MyQuickImageProvider 
    id: my_quick_image_provider
    ...

从 main.cpp 访问它会有问题。这样的设计对我来说似乎很奇怪。还有更优雅的解决方案吗?

【问题讨论】:

这个问题让我很困惑。您遇到的实际问题是什么?你的代码是什么样的? 【参考方案1】:

您没有将MyQuickImageProvider 用作QML 对象,也没有定义Q_INVOKABLE 方法,因为您无法从QML 访问图像提供程序对象。

engine.addImageProvider("my_quick_image_provider", [...]

设置访问图像的名称,例如

// qml file
Image 
    source: "image://my_quick_image_provider/name_of_my_image"

后面的部分“name_of_my_image”称为id,您可以在

中找到它
virtual QPixmap requestPixmap ( const QString &id, QSize *size, const QSize &requestedSize );

现在在你的MyQuickImageProvider 中实现requestPixmap,让它使用id 字符串来生成一个QPixmap。

我认为您可以丢弃 void setPath ( QUrl path ); 方法,因为您只需要一个图像提供程序实例来处理所有此类图像。

由于构造函数不是从基类继承的,我认为new MyQuickImageProvider(QQmlImageProviderBase::Image)); 没有意义。最好添加一个不带参数的构造函数

class MyQuickImageProvider : public QQuickImageProvider 
public:
    MyQuickImageProvider();
    // ...

并在初始化列表中包含图像类型:

MyQuickImageProvider::MyQuickImageProvider()
    : QQuickImageProvider(QQuickImageProvider::Pixmap)


【讨论】:

感谢您的回答,西蒙!据我了解,此算法将需要检查源图像是否在每次 requestPixmap 调用时发生变化(而 setPath 将允许避免每次检查)。这不能优化吗? QML 确实为您缓存了给定image:// url 的Image 的像素图,因此它假定底层图像不会经常更改。你从哪里得到图像?如果您已经有一种方法可以在图像更改时通知您,请使用信号/插槽将该信息传递给您的图像提供者。但是,一旦您掌握了基本知识,就应该将其放入后续问题中。 我有从文件加载的源图像(“大”)和小图像的 qhash;当第一次请求它的 id 时,每个小图像都是从大图像“懒惰地”裁剪并放入 qhash 的。所以我需要经常更换小图像,而大图像则要少得多。现在我将通过属性控制大图像文件名。

以上是关于使用 QQuickImageProvider 的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

QQuickImageProvider PyQt5

通过按钮单击触发带有参数的 QQuickImageProvider::requestImage()

QML 和 QQuickImageProvider 大小

使用 jquery/javascript 的正整数值 [重复]

使用 R 计算数据集中每个组的正态性

类名中的正斜杠[重复]