Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
propertybinding.qdoc
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\page qtqml-syntax-propertybinding.html
6\title Property Binding
7\brief binding object properties
8
9An object's property can be assigned a static value which stays constant until it
10is explicitly assigned a new value. However, to make the fullest use of QML and its
11built-in support for dynamic object behaviors, most QML objects use \e {property bindings}.
12
13Property bindings are a core feature of QML that lets developers specify relationships
14between different object properties. When a property's \e dependencies change in
15value, the property is automatically updated according to the specified relationship.
16
17Behind the scenes, the QML engine monitors the property's dependencies (that is,
18the variables in the binding expression). When a change is detected, the QML engine
19re-evaluates the binding expression and applies the new result to the property.
20
21\section1 Overview
22
23To create a property binding, a property is assigned a JavaScript expression that
24evaluates to the desired value. At its simplest, a binding may be a reference to
25another property. Take the following example, where the blue \l Rectangle's height
26is bound to the height of its parent:
27
28\qml
29Rectangle {
30 width: 200; height: 200
31
32 Rectangle {
33 width: 100
34 height: parent.height
35 color: "blue"
36 }
37}
38\endqml
39
40Whenever the height of the parent rectangle changes, the height of the blue
41rectangle automatically updates to be of the same value.
42
43A binding can contain any valid JavaScript expression or statement, as QML uses
44a standards compliant JavaScript engine. Bindings can access object properties,
45call methods and use built-in JavaScript objects such as \c Date and \c Math.
46Below are other possible bindings for the previous example:
47
48\code
49height: parent.height / 2
50
51height: Math.min(parent.width, parent.height)
52
53height: parent.height > 100 ? parent.height : parent.height/2
54
55height: {
56 if (parent.height > 100)
57 return parent.height
58 else
59 return parent.height / 2
60}
61
62height: someMethodThatReturnsHeight()
63\endcode
64
65Below is a more complex example involving more objects and types:
66
67\qml
68Column {
69 id: column
70 width: 200
71 height: 200
72
73 Rectangle {
74 id: topRect
75 width: Math.max(bottomRect.width, parent.width/2)
76 height: (parent.height / 3) + 10
77 color: "yellow"
78
79 TextInput {
80 id: myTextInput
81 text: "Hello QML!"
82 }
83 }
84
85 Rectangle {
86 id: bottomRect
87 width: 100
88 height: 50
89 color: myTextInput.text.length <= 10 ? "red" : "blue"
90 }
91}
92\endqml
93
94In the previous example,
95\list
96\li \c topRect.width depends on \c bottomRect.width and \c column.width
97\li \c topRect.height depends on \c column.height
98\li \c bottomRect.color depends on \c myTextInput.text.length
99\endlist
100
101In addition, any properties referenced within a JavaScript function that is
102itself used as a binding will be re-evaluated. For example, in the snippet
103below, whenever the \c enabled property of the \c Rectangle changes, the
104bindings for the \c x and \c y properties will be re-evaluated:
105
106\snippet qml/function-call-binding.qml rectangle
107
108Syntactically, bindings are allowed to be of arbitrary complexity. However, if
109a binding is overly complex - such as involving multiple lines, or imperative
110loops - it could indicate that the binding is being used for more than describing
111property relationships. Complex bindings can reduce code performance, readability,
112and maintainability. It may be a good idea to redesign components that have
113complex bindings, or at least factor the binding out into a separate function.
114As a general rule, users should not rely on the evaluation order of bindings.
115
116\sa {Positioning with Anchors}
117
118
119\target qml-javascript-assignment
120\section1 Creating Property Bindings from JavaScript
121
122A property with a binding is automatically updated as necessary. However, if the
123property is later assigned a static value from a JavaScript statement, the binding
124will be removed.
125
126For example, the \l Rectangle below initially ensures that its \c height is always
127twice its \c width. However, when the space key is pressed, the current value
128of \c {width*3} will be assigned to \c height as a \e static value. After that,
129\e {the \c height will remain fixed at this value, even if the \c width changes}.
130The assignment of the static value removes the binding.
131
132\qml
133import QtQuick 2.0
134
135Rectangle {
136 width: 100
137 height: width * 2
138
139 focus: true
140 Keys.onSpacePressed: {
141 height = width * 3
142 }
143}
144\endqml
145
146If the intention is to give the rectangle a fixed height and stop automatic
147updates, then this is not a problem. However, if the intention is to establish
148a new relationship between \c width and \c height, then the new binding
149expression must be wrapped in the Qt.binding() function instead:
150
151\qml
152import QtQuick 2.0
153
154Rectangle {
155 width: 100
156 height: width * 2
157
158 focus: true
159 Keys.onSpacePressed: {
160 height = Qt.binding(function() { return width * 3 })
161 }
162}
163\endqml
164
165Now, after the space key is pressed, the rectangle's height will continue
166auto-updating to always be three times its width.
167
168\section3 Debugging overwriting of bindings
169
170A common cause of bugs in QML applications is accidentally overwriting bindings
171with static values from JavaScript statements. To help developers track down
172problems of this kind, the QML engine is able to emit messages whenever a
173binding is lost due to imperative assignments.
174
175In order to generate such messages, you need to enable the informational output
176for the \c{qt.qml.binding.removal} logging category, for instance by calling:
177
178\code
179QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
180\endcode
181
182Please refer to the QLoggingCategory documentation for more information about
183enabling output from logging categories.
184
185Note that is perfectly reasonable in some circumstances to overwrite bindings.
186Any message generated by the QML engine should be treated as a diagnostic aid,
187and not necessarily as evidence of a problem without further investigation.
188
189\section2 Using \c this with Property Binding
190
191When creating a property binding from JavaScript, the \c this keyword can be used
192to refer to the object which receives the binding. This is helpful for resolving
193ambiguities with property names.
194
195For example, the \c Component.onCompleted handler below is defined within the
196scope of the \l Item. In this scope, \c width refers to the \l Item's width, not
197the \l Rectangle's width. To bind the \l Rectangle's \c height to its own \c width,
198the binding expression must explicitly refer to \c this.width (or alternatively,
199\c{rect.width}):
200
201\qml
202Item {
203 width: 500
204 height: 500
205
206 Rectangle {
207 id: rect
208 width: 100
209 color: "yellow"
210 }
211
212 Component.onCompleted: {
213 rect.height = Qt.binding(function() { return this.width * 2 })
214 console.log("rect.height = " + rect.height) // prints 200, not 1000
215 }
216}
217\endqml
218
219\note The value of \c this is not defined outside of property bindings.
220See \l {JavaScript Environment Restrictions} for details.
221*/