Using arbitrary QML items as cached image source

前端 未结 2 1015
深忆病人
深忆病人 2021-01-06 18:28

EDIT: The original question is still contained below, but I decided to re-title to a form that will be more useful to developers in a variety of cases, some of which describ

2条回答
  •  生来不讨喜
    2021-01-06 19:02

    What I did to optimize QtGraphicalEffects was using Item.grabToImage() :)

    This function returns QQuickItemGrabResult item which has url() function. This function returns an QUrl which can be set as a source for an Image object.

    So what you need to do is create one Image with Colorize applied on it. When it is ready use grabToImage() and after successful grab save the QUrl somewhere safe and destroy the source object.


    I suppose that you will need to change the color of the icons from time to time while the application is running. If so keep in mind that just changing the source of the Image objects so that no one uses grabbed image url will make it be released from memory. Not instantaneously but when it is needed.

    Because of some incompability my applications only manage the memory correctly if I use QGuiApplication::setAttribute(Qt::AA_UseOpenGLES); in main.cpp file.


    Also here is an important fact:

    Images are cached and shared internally, so if several Image items have the same source, only one copy of the image will be loaded. (source)


    Here is working example. The source object is Rectangle but it can easily be changed to an Image.

    import QtQuick 2.3
    import QtQuick.Window 2.2
    import QtGraphicalEffects 1.0
    
    Window {
        visible: true    
        width: 500
        height: 500
    
        property string urlOfMyIcon: ""
    
    
        Grid {
            columns: 1
            spacing: 10
            Image {
                width: 100
                height: 100
                source: urlOfMyIcon
            }
            Image {
                width: 100
                height: 100
                source: urlOfMyIcon
            }
            Image {
                width: 100
                height: 100
                source: urlOfMyIcon
            }
        }
    
        Component.onCompleted: {
            component.createObject(this)
        }
    
        Component {
            id: component
            Item {
                id: yourImageWithLoadedIconContainer
                Rectangle {
                    id: yourImageWithLoadedIcon
                    width: 80
                    height: 80
                    color: "white"
                    visible: false
    
                    // needed because I used Rectangle instead of Image
                    Component.onCompleted: {
                        colorizeEffect.grabToImage(function(result) {
                            urlOfMyIcon = result.url;
                            yourImageWithLoadedIconContainer.destroy()
                        }, Qt.size(width, height));
                    }
    
                    // use this when using Image instead of Rectangle
    //                onStatusChanged: {
    //                    if (status === Image.Ready)
    //                        colorizeEffect.grabToImage(function(result) {
    //                            urlOfMyIcon = result.url;
    //                            yourImageWithLoadedIconContainer.destroy()
    //                        }, yourImageWithLoadedIcon.sourceSize);
    //                }
                }
                Colorize {
                    id: colorizeEffect
                    anchors.fill: yourImageWithLoadedIcon
                    source: yourImageWithLoadedIcon
                    hue: 0.8
                    saturation: 0.5
                    lightness: -0.2
                    visible: false
                }
            }
        }
    }
    

提交回复
热议问题