Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Forward QML property binding in C++



  • I'd like to write a C++ adapter class that can be used in QML like this:

    Image
    {
       id: closeImage
       source: resource.svg(":/icons/close", closeImage.width, closeImage.height).Url
    }
    

    "resource" is a QObject with a Q_INVOKABLE function named "svg".
    The function accepts a resource path (QString) and a desired width and height.

        Q_INVOKABLE QVariant svg(const QString& resourcePath,
                                 const QVariant& width,
                                 const QVariant& height);
    

    It returns an intermediate QObject, which has a Property called "Url" with getter and notifier signal.

    class SvgResourceEntry : public QObject
    {
        Q_OBJECT
        QML_ANONYMOUS
        
        Q_PROPERTY(QUrl Url READ getUrl NOTIFY notifyUrlChanged)
        //...
    

    Now, if the width and height (parameters 2 and 3) change, I'd like the C++ adapter to know. In this case, I would generate a new image of the correct size, and change the returned Url (probably asynchronously with time delay, but still). Through property binding, the Image component would load the changed image.

    For this to work, I not only need the current width and height values, but actually the properties, so I can connect to the respective change signals.

    Problem is, if I pass closeImage.width and height like seen above, on the C++ side I only see a double value (QVariant-type 6), not a QQmlProperty object or something like it.

    So how could I achieve this property binding into C++?



  • @Asperamanca said in Forward QML property binding in C++:

    source: resource.svg(":/icons/close", closeImage.width, closeImage.height).Url

    source: resource.svg(":/icons/close", closeImage.width, closeImage.height).Url
    

    This would get reevaluated when the width or height changes. Just make sure the Url that it produces is slightly different each time. That way closeImage will update itself. I don't know the details of your SvgResourceEntry. What does the Url return? Is this a generated resource? Can you change the name.

    Another possibility is to blank out the Url. Then do a call later in the C++ code to update the Url. This should trigger Image to re-fetch the image.



  • @fcarney said in Forward QML property binding in C++:

    source: resource.svg(":/icons/close", closeImage.width, closeImage.height).Url
    

    This would get reevaluated when the width or height changes.

    Really? Even if resource.svg is a Q_INVOKABLE, and not a property? That has serious performance implications in other use cases...

    What does the Url return? Is this a generated resource? Can you change the name.

    I intend to use QQuickImageProvider, so I can return what I want.

    Sounds like an approach worth to try. Thanks!



  • @Asperamanca said in Forward QML property binding in C++:

    Really? Even if resource.svg is a Q_INVOKABLE, and not a property? That has serious performance implications in other use cases...

    What performance implications? Any expression that has a value change can be reevaluated.

    Now, if the width and height (parameters 2 and 3) change, I'd like the C++ adapter to know. In this case, I would generate a new image of the correct size, and change the returned Url

    Isn't this reevaluation what you want to happen?

    This is what will happen when the inputs change. You can test with a Q_INVOKABLE, but I would expect the same behavior.

        property int countint: 0
        property int changing: changeCall(countint)
    
        function changeCall(input){
            console.log("changeCall", countint)
    
            return input+1
        }
    
        onChangingChanged: console.log("changing", changing)
    
        Timer {
            interval: 1000
            running: true
            repeat: true
    
            onTriggered: {
                countint = countint + 1
            }
        }
    


  • Yes, it does make sense, when I think a little about it. And if you know that is how it works, it can actually simplify some code.

    Thanks!


Log in to reply