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