Qt Quick best practices, property bindings in QML

lavonius | 11 November, 2011 15:35

[Guestwritten by Michael Hasselmann.]

A property binding exists between two properties 'a' and 'b', written as 'a: b' such that the value of 'a' updates whenever 'b' updates. Typical use-cases are: controlling element size, controlling position of an element through anchors, dynamically changing text or images, controlling element colors or controlling button states.

In its simplest form, 'a' – once bound to 'b' – maintains the same value as 'b', for the lifetime of the property binding. In its more advanced form, 'a' is bound to an arbitrary JavaScript expression that makes use of 'b', like so: 'a: b + 1'.

It is also possible to bind 'a' to more than one property: 'a: b * c + 1'. Here, the expression will be evaluated whenever 'b' or 'c' changes.

The following table shows the value of 'a', depending on how 'b' and 'c' change their values over time.

a:b*c+1                a     b     c    
initial state          1     0     0

b = 1                  1     1     0
c = 2                  3     1     2
b = -3                -5    -3     2  

The possibilities for property bindings seem unlimited, and indeed, they can also be established between properties of different type. Consider a color property 'c' being bound to an enumeration type 'e'. The naive approach, 'c: e', will not work. But 'e' can be handed to a conversion function, done with some 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)

and it will work as expected. 'c' will update correctly even if toColor internally depends on another property but e, but such hidden dependencies are best avoided.

Never assign to bound properties. Properties are either free or bound (to other properties). Assigning a value explicitly is OK, as long as the property is free. Once it becomes bound, any new assignment would remove the previous property binding. This can be a source of bugs and as such, should be avoided.

Use property bindings over explicit state handling. Whenever state handling logic is used in QML, there is a more robust solution that relies on property binding instead and will achieve the same result. Hide the state handling behind new properties. Once the state handling logic grows, property bindings tend to scale better in terms of complexity.

Marking an item as active, through explicit state handling.

import QtQuick 1.0
// Becomes active once clicked, deactivates with next click.
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"
            }
        }
    ]
}

Marking an item as active, through a new custom property bound to item's color property. 

import QtQuick 1.0
// Becomes active once clicked, deactivates with next click.
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 explains why property bindings are used pervasively in programming with QML language. Elements should be designed as being purely dependent on their properties whenever it comes to dynamic changes. Combined with property bindings, these elements will work in a "fire-and-forget" fashion, meaning that after the initial setup, they will just keep working correctly, regardless of other considerations. This makes it possible to deal with more complex UI's but just as importantly, it also keeps the code clean and reduces the risk of introducing bugs.

Property bindings don't come for free though and under certain conditions the performance impact can become noticeable. This, however, will be material for a future article in this series.

N9 Challenge - 4 days to go

ronanmac | 11 November, 2011 15:02

A quick note to remind you have less than 4 days left to submit ideas to the N9 Challenge run by Nokia Crowdsourcing at www.ideasproject.com/N9. So far more than 2,000 ideas have been submitted, everything from features requests to new hardware concepts to innovative UX enhancements.

The ideas will be reviewed, and the best will be evaluated by a jury consisting of leading designers from Nokia:

  • Nikki Barton - VP, Smart Devices UX Design
  • Peter Skillman - VP Services & MeeGo Design
  • Anton Fahlgren - Principal Designer

The lucky winners get a brand new N9. For others, they have a chance to influence the jury.  The big thing is that the ideas can live on, even after the challenge.

 

Nokia Developer aims to help you create apps and publish them so you can connect with users around the world.

京ICP备05048969号  © Copyright Nokia 2013 All rights reserved