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