Best Qt Quick Tricks: Binding Properties in QML

    The binding between the two properties (property binding) “a” and “b”, declared as “a: b”, updates the value of “a” whenever “b” is updated. Linking properties finds practical application in controlling the size of an element, controlling the position of an element using an anchor, dynamically changing text or images, controlling the color of an element or the state of buttons.

    In its simplest form, “a” associated with “b” retains the same meaning as “b” for the duration of the binding of properties. In a more advanced form, “a” binds to an arbitrary JavaScript expression that uses “b” as “a: b + 1”.

    You can associate more than two properties - “a: b * c + 1”. In this case, the expression will be counted each time “b” or “c” is changed.

    The table below describes the value of “a”, depending on how “b” and “c” change over time.

    a: b * c + 1abc
    initial values100
    b = 1110
    c = 2312
    b = -3-5-32


    The possibilities for binding properties seem limitless, and indeed, they can be set between properties of different types. Consider the color property “c” associated with the enumeration “e”. Of course, a simple c: e binding will not work. But we can convert “e” using JavaScript:

    function toColor(e)
    {
        switch(e)
        {
            case highlighted: return "blue";
            case inactive: return "white";
            default: return "black";
        }
    }
    


    Now the property binding can be written as:
    c: toColor(e)


    It will work as expected: “c” will be updated correctly even if toColor itself depends on another property (except, of course, “e”) - however, it is better to try to avoid such hidden dependencies.
    Assigning values ​​to related properties should be avoided. Properties can be free (free properties) or related (with other properties; bound properties). Assigning an explicit value is allowed if the property is free. Once a property becomes bound, each new assignment will remove the previous property relationship. This can be a source of error and should therefore be avoided.

    You can use property binding instead of explicit state management. If QML uses state control logic, it is best to use a more advanced solution based on property binding. The result will be the same, but state processing will be hidden behind the new properties. As soon as the state management logic starts to become more complex, it becomes noticeable that the scalability of property binding is much higher (within the scope of complexity of scaling).

    We mark the element as active using explicit state processing.

    import QtQuick 1.0
    // Становится активным после клика, отключается со следующим кликом.
    Rectangle {
        id: canvas
        anchors.fill: parent
        color: "green"
        MouseArea {
            anchors.fill: parent
            onClicked: {
                canvas.state == "activated" ? canvas.state = ""
                                            : canvas.state = "activated"
            }
        }
        states: [
            State {
                name:  "activated"
                PropertyChanges {
                    target: canvas
                    color: "red"
                }
            }
        ]
    }


    We mark the element as active using a new property associated with the color of the element.

    import QtQuick 1.0
    // Становится активным после клика, отключается со следующим кликом.
    Rectangle {
        id: canvas
        anchors.fill: parent
        property bool activated: false
        color: activated ? "red"
                         : "green"
        MouseArea {
            anchors.fill: parent
            onClicked: {
                canvas.activated = !canvas.activated
            }
        }
    }


    The flexibility and ease of use of property binding explains why it is used universally in QML programming. When it comes to dynamic changes, elements must necessarily depend on their properties. In combination with the binding of properties, these elements will work on "autopilot": after the initial setup, the elements will work correctly, regardless of other factors. This, in turn, allows you to work with more complex interfaces, while maintaining the purity of the code and reducing the risk of errors.

    However, you have to pay for the advantages of using property binding - under certain conditions, performance can noticeably drop. However, this is a separate topic, which will be devoted to the next article.

    Also popular now: