QML 和 QQuickImageProvider 大小

Posted

技术标签:

【中文标题】QML 和 QQuickImageProvider 大小【英文标题】:QML and QQuickImageProvider size 【发布时间】:2017-09-12 11:10:42 【问题描述】:

我有一个 QML 应用程序,其中显示来自图像提供程序的 QImages。我写了一个继承自 QQuickImageProvider 的类。在 QML 中,我有两个 Image 对象。

ColumnLayout 
    RowLayout 
        Image 
            source: "image://backend/1"
            width: parent.width/2
        
        Image 
            source: "image://backend/1"
            width: parent.width/2
        

这是提供者的代码:

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

    QSize req(requestedSize.width()<0?100:requestedSize.width(),
              requestedSize.height()<0?100:requestedSize.height());
    try 
        QImage ret=assign.at(id)->scaled(req,Qt::KeepAspectRatio);
        *size=ret.size();
        return ret;
    
    catch( out_of_range ) 
        QImage ret(req,QImage::Format_RGB16);
        *size=ret.size();
    ret.fill(QColor(qrand()/(RAND_MAX/255),qrand()/(RAND_MAX/255),qrand()/(RAND_MAX/255)).rgba());

        return ret;
    

到目前为止它可以工作,这意味着图片已显示。 现在我希望这些图片被缩放。我希望每张图片都填满我的应用程序窗口的一半,但它不起作用。我设置的每个宽度都会被忽略,并且每次请求的大小无效时,图像提供程序都会得到。

我必须做些什么才能实现这一目标?

【问题讨论】:

可能你忽略了QQuickImageProvider::requestImagerequestedSize 参数。如果您希望得到正确答案,您应该向我们展示您的代码,包括 C++ 和 QML(缩放方法?) 如果大小无效,我忽略它,还有什么?但问题是我返回的图片必须有大小(我将它设置为 100x100)并且显示的图片有这个大小,但我想在 QML 中更改大小 @folibis 除了被覆盖的方法外,不需要查看任何内容。这个方法应该独立于调用者代码。 【参考方案1】:

由于您的项目大小由Layout 管理,您应该设置布局的首选大小而不是项目的大小:

RowLayout 
    anchors.fill: parent
    Image 
        source: "image://backend/1"
        Layout.preferredHeight: parent.height
        Layout.preferredWidth: parent.width / 2
    
    Image 
        source: "image://backend/1"
        Layout.preferredHeight: parent.height
        Layout.preferredWidth: parent.width / 2
    

更多信息可以找到here

【讨论】:

谢谢,但您的程序中有一个小而重要的错误。布局在元素之间有间距。如果你有两个元素与 parent/2 窗口增长和增长,因为有一个绑定循环。 好的,只需在布局中添加spacing: 0【参考方案2】:

(缓存)图像提供程序的正确实现示例:

// videoplayerimageprovider.hpp:

#pragma once

#include <QtQuick>

Q_DECLARE_LOGGING_CATEGORY(videoPlayerImageProviderCategory)

class VideoPlayerImageProvider
        : public QQuickImageProvider


    Q_DECLARE_TR_FUNCTIONS(VideoPlayerImageProvider)

public :

    VideoPlayerImageProvider(QQmlEngine * const engine);

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

private :

    QQmlEngine * const engine;
    QHash< QString, QImage > images;

;

// videoplayerimageprovider.cpp:

#include "videoplayerimageprovider.hpp"

Q_LOGGING_CATEGORY(videoPlayerImageProviderCategory, "videoPlayerImageProvider")

VideoPlayerImageProvider::VideoPlayerImageProvider(QQmlEngine * const engine)
    : QQuickImageProviderQQuickImageProvider::Image
    , engineengine
 ; 

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

    const auto selector = QQmlFileSelector::get(engine)->selector();
    const auto imagePath = selector->select(QStringLiteral(":/images/videoplayer/%1").arg(id));
#if 0
    qDebug().noquote()
            << tr("Selected filepath: %1. Installed file selectors: %2")
               .arg(imagePath, selector->allSelectors().join(QStringLiteral(", ")));
#endif
    QImage image;
    if (!images.contains(imagePath)) 
        QImageReader imageReaderimagePath;
        image = imageReader.read();
        if (image.isNull()) 
            qCCritical(videoPlayerImageProviderCategory).noquote()
                    << tr("Unable to read image from %1: %3 (%2)")
                       .arg(imagePath, imageReader.errorString()).arg(imageReader.error());
         else 
            images.insert(imagePath, image);
        
     else 
        image = images[imagePath];
    
    if (size)  // should be assigned size of original image
        *size = image.size();
    
    if (requestedSize.isEmpty() || (image.size() == requestedSize))  // avoid returning invalid QImage
        return image;
    
    return image.scaled(requestedSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

如果您的图像文件不需要文件选择器,则可以删除 engineselector

我注意到,在加载场景期间,没有一次调用相同的 id。首先是尺寸无效。

【讨论】:

以上是关于QML 和 QQuickImageProvider 大小的主要内容,如果未能解决你的问题,请参考以下文章

使用 QQuickImageProvider 的正确方法是啥?

QQuickImageProvider PyQt5

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

2 个不同 QML 之间的 QML 信号和时隙

C++ 和 QML 中的 QT QML 项

列数可变的 QML 中继器和 QML 网格布局