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
dynamicobjectcreation.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-javascript-dynamicobjectcreation.html
6
\meta {keywords} {qmltopic}
7
\title Dynamic QML Object Creation from JavaScript
8
\brief instantiating and managing QML objects from JavaScript
9
10
QML supports the dynamic creation of objects from within JavaScript. This is
11
useful to delay instantiation of objects until necessary, thereby improving
12
application startup time. It also allows visual objects to be dynamically
13
created and added to the scene in reaction to user input or other events.
14
15
\warning Objects should not be dynamically created from untrusted sources. The
16
limitations \l{Qt Qml and JavaScript Sources}{for static QML sources} apply
17
equally to dynamic object creation.
18
19
\section1 Creating Objects Dynamically
20
21
There are two ways to create objects dynamically from JavaScript. You can
22
either call \l {QtQml::Qt::createComponent()}{Qt.createComponent()} to
23
dynamically create a \l Component object, or use \l{QtQml::Qt::createQmlObject()}
24
{Qt.createQmlObject()} to create an object from a string of QML. Creating a
25
component is better if you have an existing component defined in a QML document
26
and you want to dynamically create instances of that component. Otherwise,
27
creating an object from a string of QML is useful when the object QML itself is
28
generated at runtime.
29
30
31
\section2 Creating a Component Dynamically
32
33
To dynamically load a component defined in a QML file, call the
34
\l {QtQml::Qt::createComponent()}{Qt.createComponent()} function in the
35
\l {QmlGlobalQtObject}{Qt object}.
36
This function takes the URL of the QML file as its only argument and creates
37
a \l Component object from this URL.
38
39
Once you have a \l Component, you can call its \l {Component::createObject()}
40
{createObject()} method to create an instance of the component. This function
41
can take one or two arguments:
42
\list
43
\li The first is the parent for the new object. The parent can be a graphical
44
object (i.e. of the \l Item type) or non-graphical object (i.e. of the
45
\l QtObject or C++ QObject type). Only graphical objects with graphical
46
parent objects will be rendered to the \l {Qt Quick} visual canvas. If you wish
47
to set the parent later you can safely pass \c null to this function.
48
\li The second is optional and is a map of property-value pairs that define
49
initial any property values for the object. Property values specified by
50
this argument are applied to the object before its creation is finalized,
51
avoiding binding errors that may occur if particular properties must be
52
initialized to enable other property bindings. Additionally, there are
53
small performance benefits when compared to defining property values and
54
bindings after the object is created.
55
\endlist
56
57
Here is an example. First there is \c Sprite.qml, which defines a simple QML component:
58
59
\snippet qml/Sprite.qml 0
60
61
Our main application file, \c main.qml, imports a \c componentCreation.js
62
JavaScript file that will create \c Sprite objects:
63
64
\snippet qml/createComponent.qml 0
65
66
Here is \c componentCreation.js. Notice it checks whether the component
67
\l{Component::status}{status} is \c Component.Ready before calling
68
\l {Component::createObject()}{createObject()} in case the QML file is loaded
69
over a network and thus is not ready immediately.
70
71
\snippet qml/componentCreation.js vars
72
\codeline
73
\snippet qml/componentCreation.js func
74
\snippet qml/componentCreation.js remote
75
\snippet qml/componentCreation.js func-end
76
\codeline
77
\snippet qml/componentCreation.js finishCreation
78
79
If you are certain the QML file to be loaded is a local file, you could omit
80
the \c finishCreation() function and call \l {Component::createObject()}
81
{createObject()} immediately:
82
83
\snippet qml/componentCreation.js func
84
\snippet qml/componentCreation.js local
85
\snippet qml/componentCreation.js func-end
86
87
Notice in both instances, \l {Component::createObject()}{createObject()} is
88
called with \c appWindow passed as the parent argument, since the dynamically
89
created object is a visual (Qt Quick) object. The created object will become a
90
child of the \c appWindow object in \c main.qml, and appear in the scene.
91
92
When using files with relative paths, the path should
93
be relative to the file where \l {QtQml::Qt::createComponent()}
94
{Qt.createComponent()} is executed.
95
96
To connect signals to (or receive signals from) dynamically created objects,
97
use the signal \c connect() method. See
98
\l{Signal and Handler Event System#Connecting Signals to Methods and Signals}
99
{Connecting Signals to Methods and Signals} for more information.
100
101
It is also possible to instantiate components without blocking via the
102
\l {Component::incubateObject()}{incubateObject()} function.
103
104
\section2 Creating an Object from a String of QML
105
106
\warning Creating objects from a string of QML is extremely slow since the engine has to compile the
107
passed QML string every time you do it. Furthermore, it's very easy to produce invalid QML when
108
programmatically constructing QML code. It's much better to keep your QML components as separate
109
files and add properties and methods to customize their behavior than to produce new components by
110
string manipulation.
111
112
If the QML is not defined until runtime, you can create a QML object from
113
a string of QML using the \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}
114
function, as in the following example:
115
116
\snippet qml/createQmlObject.qml 0
117
118
The first argument is the string of QML to create. Just like in a new file,
119
you will need to import any types you wish to use. The second argument is the
120
parent object for the new object, and the parent argument semantics which apply
121
to components are similarly applicable for \c createQmlObject().
122
The third argument is the file path to associate with the new object; this is
123
used for error reporting.
124
125
If the string of QML imports files using relative paths, the path should be
126
relative to the file in which the parent object (the second argument to the
127
method) is defined.
128
129
\important When building static QML applications,
130
QML files are scanned to detect import dependencies. That way, all
131
necessary plugins and resources are resolved at compile time.
132
However, only explicit import statements are considered (those found at
133
the top of a QML file), and not import statements enclosed within string literals.
134
To support static builds, you therefore need to ensure that QML files
135
using \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()},
136
explicitly contain all necessary imports at the top of the file in addition
137
to inside the string literals.
138
139
\section1 Maintaining Dynamically Created Objects
140
141
When managing dynamically created objects, you must ensure the creation context
142
outlives the created object. Otherwise, if the creation context is destroyed
143
first, the bindings and signal handlers in the dynamic object will no longer work.
144
145
The actual creation context depends on how an object is created:
146
147
\list
148
\li If \l {QtQml::Qt::createComponent()}{Qt.createComponent()} is used, the
149
creation context is the QQmlContext in which this method is called
150
\li If \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()} is called, the
151
creation context is the context of the parent object passed to this method
152
\li If a \c {Component{}} object is defined and \l {Component::createObject()}
153
{createObject()} or \l {Component::incubateObject()}{incubateObject()} is
154
called on that object, the creation context is the context in which the
155
\c Component is defined
156
\endlist
157
158
Also, note that while dynamically created objects may be used the same as other
159
objects, they do not have an id in QML.
160
161
162
\section1 Deleting Objects Dynamically
163
164
In many user interfaces, it is sufficient to set a visual object's opacity to 0
165
or to move the visual object off the screen instead of deleting it. If you have
166
lots of dynamically created objects, however, you may receive a worthwhile
167
performance benefit if unused objects are deleted.
168
169
Note that you should never manually delete objects that were dynamically
170
created by convenience QML object factories (such as \l Loader and
171
\l Repeater). Also, you should avoid deleting objects that you did not
172
dynamically create yourself.
173
174
Items can be deleted using the \c destroy() method. This method has an optional
175
argument (which defaults to 0) that specifies the approximate delay in
176
milliseconds before the object is to be destroyed.
177
178
Here is an example. The \c application.qml creates five instances of the
179
\c SelfDestroyingRect.qml component. Each instance runs a NumberAnimation,
180
and when the animation has finished, calls \c destroy() on its root object to
181
destroy itself:
182
183
\table
184
\row
185
\li \c application.qml
186
\li \snippet qml/dynamicObjects-destroy.qml 0
187
188
\row
189
\li \c SelfDestroyingRect.qml
190
\li \snippet qml/SelfDestroyingRect.qml 0
191
192
\endtable
193
194
Alternatively, the \c application.qml could have destroyed the created object
195
by calling \c object.destroy().
196
197
Note that it is safe to call destroy() on an object within that object. Objects
198
are not destroyed the instant destroy() is called, but are cleaned up sometime
199
between the end of that script block and the next frame (unless you specified a
200
non-zero delay).
201
202
Note also that if a \c SelfDestroyingRect instance was created statically like
203
this:
204
205
\qml
206
Item {
207
SelfDestroyingRect {
208
// ...
209
}
210
}
211
\endqml
212
213
This would result in an error, since objects can only be dynamically
214
destroyed if they were dynamically created.
215
216
Objects created with \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}
217
can similarly be destroyed using \c destroy():
218
219
\snippet qml/createQmlObject.qml 0
220
\snippet qml/createQmlObject.qml destroy
221
222
*/
qtdeclarative
src
qml
doc
src
javascript
dynamicobjectcreation.qdoc
Generated on
for Qt by
1.16.1