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