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