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
10QML supports the dynamic creation of objects from within JavaScript. This is
11useful to delay instantiation of objects until necessary, thereby improving
12application startup time. It also allows visual objects to be dynamically
13created 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
16limitations \l{Qt Qml and JavaScript Sources}{for static QML sources} apply
17equally to dynamic object creation.
18
19\section1 Creating Objects Dynamically
20
21There are two ways to create objects dynamically from JavaScript. You can
22either call \l {QtQml::Qt::createComponent()}{Qt.createComponent()} to
23dynamically 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
25component is better if you have an existing component defined in a QML document
26and you want to dynamically create instances of that component. Otherwise,
27creating an object from a string of QML is useful when the object QML itself is
28generated at runtime.
29
30
31\section2 Creating a Component Dynamically
32
33To 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}.
36This function takes the URL of the QML file as its only argument and creates
37a \l Component object from this URL.
38
39Once you have a \l Component, you can call its \l {Component::createObject()}
40{createObject()} method to create an instance of the component. This function
41can 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
57Here is an example. First there is \c Sprite.qml, which defines a simple QML component:
58
59\snippet qml/Sprite.qml 0
60
61Our main application file, \c main.qml, imports a \c componentCreation.js
62JavaScript file that will create \c Sprite objects:
63
64\snippet qml/createComponent.qml 0
65
66Here 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
69over 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
79If you are certain the QML file to be loaded is a local file, you could omit
80the \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
87Notice in both instances, \l {Component::createObject()}{createObject()} is
88called with \c appWindow passed as the parent argument, since the dynamically
89created object is a visual (Qt Quick) object. The created object will become a
90child of the \c appWindow object in \c main.qml, and appear in the scene.
91
92When using files with relative paths, the path should
93be relative to the file where \l {QtQml::Qt::createComponent()}
94{Qt.createComponent()} is executed.
95
96To connect signals to (or receive signals from) dynamically created objects,
97use 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
101It 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
107passed QML string every time you do it. Furthermore, it's very easy to produce invalid QML when
108programmatically constructing QML code. It's much better to keep your QML components as separate
109files and add properties and methods to customize their behavior than to produce new components by
110string manipulation.
111
112If the QML is not defined until runtime, you can create a QML object from
113a string of QML using the \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}
114function, as in the following example:
115
116\snippet qml/createQmlObject.qml 0
117
118The first argument is the string of QML to create. Just like in a new file,
119you will need to import any types you wish to use. The second argument is the
120parent object for the new object, and the parent argument semantics which apply
121to components are similarly applicable for \c createQmlObject().
122The third argument is the file path to associate with the new object; this is
123used for error reporting.
124
125If the string of QML imports files using relative paths, the path should be
126relative to the file in which the parent object (the second argument to the
127method) is defined.
128
129\important When building static QML applications,
130QML files are scanned to detect import dependencies. That way, all
131necessary plugins and resources are resolved at compile time.
132However, only explicit import statements are considered (those found at
133the top of a QML file), and not import statements enclosed within string literals.
134To support static builds, you therefore need to ensure that QML files
135using \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()},
136explicitly contain all necessary imports at the top of the file in addition
137to inside the string literals.
138
139\section1 Maintaining Dynamically Created Objects
140
141When managing dynamically created objects, you must ensure the creation context
142outlives the created object. Otherwise, if the creation context is destroyed
143first, the bindings and signal handlers in the dynamic object will no longer work.
144
145The 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
158Also, note that while dynamically created objects may be used the same as other
159objects, they do not have an id in QML.
160
161
162\section1 Deleting Objects Dynamically
163
164In many user interfaces, it is sufficient to set a visual object's opacity to 0
165or to move the visual object off the screen instead of deleting it. If you have
166lots of dynamically created objects, however, you may receive a worthwhile
167performance benefit if unused objects are deleted.
168
169Note that you should never manually delete objects that were dynamically
170created by convenience QML object factories (such as \l Loader and
171\l Repeater). Also, you should avoid deleting objects that you did not
172dynamically create yourself.
173
174Items can be deleted using the \c destroy() method. This method has an optional
175argument (which defaults to 0) that specifies the approximate delay in
176milliseconds before the object is to be destroyed.
177
178Here is an example. The \c application.qml creates five instances of the
179\c SelfDestroyingRect.qml component. Each instance runs a NumberAnimation,
180and when the animation has finished, calls \c destroy() on its root object to
181destroy 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
194Alternatively, the \c application.qml could have destroyed the created object
195by calling \c object.destroy().
196
197Note that it is safe to call destroy() on an object within that object. Objects
198are not destroyed the instant destroy() is called, but are cleaned up sometime
199between the end of that script block and the next frame (unless you specified a
200non-zero delay).
201
202Note also that if a \c SelfDestroyingRect instance was created statically like
203this:
204
205\qml
206Item {
207 SelfDestroyingRect {
208 // ...
209 }
210}
211\endqml
212
213This would result in an error, since objects can only be dynamically
214destroyed if they were dynamically created.
215
216Objects created with \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}
217can similarly be destroyed using \c destroy():
218
219\snippet qml/createQmlObject.qml 0
220\snippet qml/createQmlObject.qml destroy
221
222*/