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
scope.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
\page qtqml-documents-scope.html
5
\title Scope and Naming Resolution
6
\brief overview of scope and naming resolution
7
\ingroup explanations-programminglanguages
8
9
QML property bindings, inline functions, and imported JavaScript files all
10
run in a JavaScript scope. Scope controls which variables an expression can
11
access, and which variable takes precedence when two or more names conflict.
12
13
As JavaScript's built-in scope mechanism is very simple, QML enhances it to fit
14
more naturally with the QML language extensions.
15
16
\section1 JavaScript Scope
17
18
QML's scope extensions do not interfere with JavaScript's natural scoping.
19
JavaScript programmers can reuse their existing knowledge when programming
20
functions, property bindings or imported JavaScript files in QML.
21
22
In the following example, the \c {addConstant()} method will add 13 to the
23
parameter passed just as the programmer would expect irrespective of the
24
value of the QML object's \c a and \c b properties.
25
26
\qml
27
QtObject {
28
property int a: 3
29
property int b: 9
30
31
function addConstant(b) {
32
var a = 13;
33
return b + a;
34
}
35
}
36
\endqml
37
38
That QML respects JavaScript's normal scoping rules even applies in bindings.
39
This totally evil, abomination of a binding will assign 12 to the QML object's
40
\c a property.
41
42
\qml
43
QtObject {
44
property int a
45
46
a: { var a = 12; a; }
47
}
48
\endqml
49
50
Every JavaScript expression, function or file in QML has its own unique
51
variable object. Local variables declared in one will never conflict
52
with local variables declared in another.
53
54
\section1 Type Names and Imported JavaScript Files
55
56
\l {QML Documents} include import statements that define the type names
57
and JavaScript files visible to the document. In addition to their use in the
58
QML declaration itself, type names are used by JavaScript code when accessing
59
\l {Attached Properties and Attached Signal Handlers}{attached properties} and enumeration values.
60
61
The effect of an import applies to every property binding, and JavaScript
62
function in the QML document, even those in nested inline components. The
63
following example shows a simple QML file that accesses some enumeration
64
values and calls an imported JavaScript function.
65
66
\qml
67
import QtQuick 2.0
68
import "code.js" as Code
69
70
ListView {
71
snapMode: ListView.SnapToItem
72
73
delegate: Component {
74
Text {
75
elide: Text.ElideMiddle
76
text: "A really, really long string that will require eliding."
77
color: Code.defaultColor()
78
}
79
}
80
}
81
\endqml
82
83
\section1 Binding Scope Object
84
85
An object which has a \l{Property Binding}{property binding} is known as the
86
binding's \e{scope object}. In the following example, the \l Item object is
87
the binding's scope object.
88
89
\qml
90
Item {
91
anchors.left: parent.left
92
}
93
\endqml
94
95
Bindings have access to the scope object's properties without qualification.
96
In the previous example, the binding accesses the \l Item's \c parent property
97
directly, without needing any form of object prefix. QML introduces a more
98
structured, object-oriented approach to JavaScript, and consequently does not
99
require the use of the JavaScript \c this property.
100
101
Care must be used when accessing \l {Attached Properties and Attached Signal Handlers}
102
{attached properties} from bindings due
103
to their interaction with the scope object. Conceptually attached properties
104
exist on \e all objects, even if they only have an effect on a subset of those.
105
Consequently unqualified attached property reads will always resolve to an
106
attached property on the scope object, which is not always what the programmer
107
intended.
108
109
For example, the \l PathView type attaches interpolated value properties to
110
its delegates depending on their position in the path. As PathView only
111
meaningfully attaches these properties to the root object in the delegate, any
112
sub-object that accesses them must explicitly qualify the root object, as shown
113
below.
114
115
\qml
116
PathView {
117
delegate: Component {
118
Rectangle {
119
id: root
120
Image {
121
scale: root.PathView.scale
122
}
123
}
124
}
125
}
126
\endqml
127
128
If the \l Image object omitted the \c root prefix, it would inadvertently access
129
the unset \c {PathView.scale} attached property on itself.
130
131
\section1 Component Scope
132
133
Each QML component in a QML document defines a logical scope. Each document
134
has at least one root component, but can also have other inline sub-components.
135
The component scope is the union of the object ids within the component and the
136
component's root object's properties.
137
138
\code
139
Item {
140
property string title
141
142
Text {
143
id: titletype
144
text: "<b>" + title + "</b>"
145
font.pixelSize: 22
146
anchors.top: parent.top
147
}
148
149
Text {
150
text: titletype.text
151
font.pixelSize: 18
152
anchors.bottom: parent.bottom
153
}
154
}
155
\endcode
156
157
The example above shows a simple QML component that displays a rich text title
158
string at the top, and a smaller copy of the same text at the bottom. The first
159
\c Text type directly accesses the component's \c title property when
160
forming the text to display. That the root type's properties are directly
161
accessible makes it trivial to distribute data throughout the component.
162
163
The second \c Text type uses an id to access the first's text directly. IDs
164
are specified explicitly by the QML programmer so they always take precedence
165
over other property names (except for those in the \l {JavaScript Scope}). For
166
example, in the unlikely event that the binding's \l {Binding Scope Object}{scope
167
object} had a \c titletype property in the previous example, the \c titletype
168
id would still take precedence.
169
170
\section1 Component Instance Hierarchy
171
172
In QML, component instances connect their component scopes together to form a
173
scope hierarchy. Component instances can directly access the component scopes of
174
their ancestors.
175
176
The easiest way to demonstrate this is with inline sub-components whose component
177
scopes are implicitly scoped as children of the outer component.
178
179
\qml
180
Item {
181
property color defaultColor: "blue"
182
183
ListView {
184
delegate: Component {
185
Rectangle {
186
color: defaultColor
187
}
188
}
189
}
190
}
191
\endqml
192
193
The component instance hierarchy allows instances of the delegate component
194
to access the \c defaultColor property of the \c Item type. Of course,
195
had the delegate component had a property called \c defaultColor that would
196
have taken precedence.
197
198
The component instance scope hierarchy extends to out-of-line components, too.
199
In the following example, the \c TitlePage.qml component creates two
200
\c TitleText instances. Even though the \c TitleText type is in a separate
201
file, it still has access to the \c title property when it is used from within
202
the \c TitlePage. QML is a dynamically scoped language - depending on where it
203
is used, the \c title property may resolve differently.
204
205
\qml
206
// TitlePage.qml
207
import QtQuick 2.0
208
Item {
209
property string title
210
211
TitleText {
212
size: 22
213
anchors.top: parent.top
214
}
215
216
TitleText {
217
size: 18
218
anchors.bottom: parent.bottom
219
}
220
}
221
222
// TitleText.qml
223
import QtQuick 2.0
224
Text {
225
property int size
226
text: "<b>" + title + "</b>"
227
font.pixelSize: size
228
}
229
\endqml
230
231
Dynamic scoping is very powerful, but it must be used cautiously to prevent
232
the behavior of QML code from becoming difficult to predict. In general it
233
should only be used in cases where the two components are already tightly
234
coupled in another way. When building reusable components, it is preferable
235
to use property interfaces, like this:
236
237
\qml
238
// TitlePage.qml
239
import QtQuick 2.0
240
Item {
241
id: root
242
property string title
243
244
TitleText {
245
title: root.title
246
size: 22
247
anchors.top: parent.top
248
}
249
250
TitleText {
251
title: root.title
252
size: 18
253
anchors.bottom: parent.bottom
254
}
255
}
256
257
// TitleText.qml
258
import QtQuick 2.0
259
Text {
260
property string title
261
property int size
262
263
text: "<b>" + title + "</b>"
264
font.pixelSize: size
265
}
266
\endqml
267
268
\section2 Do Not Reference Root Object \c id From Other QML Components
269
270
Avoid accessing the \c id of a root object from outside the QML file where
271
it is defined. \c id values are only valid within the same document, and relying
272
on them from other components breaks encapsulation and component boundaries.
273
274
\code
275
// Main.qml
276
import QtQuick
277
278
Item {
279
id: root
280
CustomItem { }
281
}
282
283
// CustomItem.qml
284
import QtQuick
285
286
Rectangle {
287
width: root.width
288
height: root.height / 2
289
color: "red"
290
}
291
\endcode
292
293
In the above example, \c root is not declared in \c CustomItem.qml. The code still works
294
because \c CustomItem is instantiated in a context where \c root exists, which is
295
permitted by QML’s dynamic scoping rules. However, this creates an implicit dependency on
296
the outer scope, making the component unreliable and harder to reuse when it is loaded
297
dynamically or used in a different context. This pattern can also lead to subtle bugs.
298
For example, if another object in the scope chain uses the same \c id, it may shadow the
299
expected one, resulting in unexpected behaviour.
300
301
To make components reliable and reusable, access external state only through
302
explicit properties, property aliases, or signals. Avoid relying on outer-scope
303
\c id values.
304
305
The following example replaces dynamic scoping with an explicit component API.
306
307
\code
308
// Main.qml
309
import QtQuick
310
import QtQuick.Window
311
312
Window {
313
id: root
314
width: 400
315
height: 300
316
visible: true
317
318
CustomItem {
319
width: root.width
320
height: root.height
321
boxColor: "blue"
322
}
323
}
324
325
// CustomItem.qml
326
import QtQuick
327
328
Item {
329
id: container
330
property alias boxColor: rect.color
331
332
Rectangle {
333
id: rect
334
width: container.width
335
height: container.height / 2
336
color: "red"
337
}
338
}
339
\endcode
340
341
Apply the same rule to all internal objects declared with an \c id inside a component.
342
343
\code
344
// MyItem.qml
345
import QtQuick
346
347
Item {
348
Item {
349
id: internalCounter
350
property int count: 5
351
}
352
}
353
354
// main.qml
355
import QtQuick
356
357
MyItem {
358
Component.onCompleted: {
359
console.log(internalCounter.count);
360
}
361
}
362
\endcode
363
364
In the above example, accessing the \c id \c internalCounter from another QML file causes a
365
\c ReferenceError because an \c id is document-local and cannot be accessed outside the
366
QML file in which it is declared.
367
368
If an internal object needs to expose state or behaviour, expose it explicitly through properties,
369
property aliases, or signals.
370
371
The following example exposes the internal state through an explicit component API instead of
372
relying on direct access to a document-local \c id.
373
374
\code
375
// MyItem.qml
376
import QtQuick
377
378
Item {
379
Item {
380
id: internalCounter
381
property int count: 5
382
}
383
property alias internalCount: internalCounter.count
384
}
385
386
// main.qml
387
import QtQuick
388
389
MyItem {
390
Component.onCompleted: {
391
console.log(internalCount);
392
}
393
}
394
\endcode
395
396
This helps maintain clear component boundaries and supports better scalability
397
and testability.
398
399
\section1 Overridden Properties
400
401
QML permits property names defined in an object declaration to be overridden by properties
402
declared within another object declaration that extends the first. For example:
403
404
\qml
405
// Displayable.qml
406
import QtQuick 2.0
407
Item {
408
property string title
409
property string detail
410
411
Text {
412
text: "<b>" + title + "</b><br>" + detail
413
}
414
415
function getTitle() { return title }
416
function setTitle(newTitle) { title = newTitle }
417
}
418
419
// Person.qml
420
import QtQuick 2.0
421
Displayable {
422
property string title
423
property string firstName
424
property string lastName
425
426
function fullName() { return title + " " + firstName + " " + lastName }
427
}
428
\endqml
429
430
Here, the name \c title is given to both the heading of the output text for Displayable,
431
and also to the honorific title of the Person object.
432
433
An overridden property is resolved according to the scope in which it is referenced.
434
Inside the scope of the Person component, or from an external scope that refers
435
to an instance of the Person component, \c title resolves to the property
436
declared inside Person.qml. The \c fullName function will refer to the \c title
437
property declared inside Person.
438
439
Inside the Displayable component, however, \c title refers to the property
440
declared in Displayable.qml. The getTitle() and setTitle() functions, and the
441
binding for the \c text property of the Text object will all refer to the \c title
442
property declared in the Displayable component.
443
444
Despite sharing the same name, the two properties are entirely separate. An
445
onChanged signal handler for one of the properties will not be triggered by
446
a change to the other property with the same name. An alias to either property
447
will refer to one or the other, but not both.
448
449
\section1 JavaScript Global Object
450
451
QML disallows type, id and property names that conflict with the properties
452
on the global object to prevent any confusion. Programmers can be confident
453
that \c Math.min(10, 9) will always work as expected!
454
455
See \l {JavaScript Host Environment} for more information.
456
457
*/
qtdeclarative
src
qml
doc
src
qmllanguageref
documents
scope.qdoc
Generated on
for Qt by
1.16.1