Qt Reference Documentation

Dynamic Object Management

QML provides a number of ways to dynamically create and manage QML objects. The Loader, Repeater, ListView, GridView and PathView elements all support dynamic object management. Objects can also be created and managed from C++, and this is the preferred method for hybrid QML/C++ applications (see Using QML in C++ Applications).

QML also supports the dynamic creation of objects from within JavaScript code. This is useful if the existing QML elements do not fit the needs of your application, and there are no C++ components involved.

Creating Objects Dynamically

There are two ways to create objects dynamically from JavaScript. You can either call Qt.createComponent() to create a component which instantiates items, or use Qt.createQmlObject() to create an item from a string of QML. Creating a component is better if you have a predefined item, and you want to create dynamic instances of that item; creating an item from a string of QML is useful when the item QML itself is generated at runtime.

If you have a component specified in a QML file, you can dynamically load it with the Qt.createComponent() function on the QML Global Object. This function takes the URL of the QML file as its only argument and returns a component object which can be used to create and load that QML file.

Once you have a component you can use its createObject() method to create an instance of the component. This function takes exactly one argument, which is the parent for the new item. Since graphical items will not appear on the scene without a parent, it is recommended that you set the parent this way. However, if you wish to set the parent later you can safely pass null to this function.

Here is an example. Here is a Sprite.qml, which defines a simple QML component:

 import Qt 4.7

 Rectangle { width: 80; height: 50; color: "red" }

Our main application file, main.qml, imports a componentCreation.js JavaScript file that will create Sprite objects:

 import Qt 4.7
 import "componentCreation.js" as MyModule

 Rectangle {
     id: appWindow
     width: 300; height: 300

     Component.onCompleted: MyModule.createSpriteObjects();
 }

Here is componentCreation.js. Remember that QML files that might be loaded over the network cannot be expected to be ready immediately:

 var component;
 var sprite;

 function finishCreation() {
     if (component.status == Component.Ready) {
         sprite = component.createObject(appWindow);
         if (sprite == null) {
             // Error Handling
         } else {
             sprite.x = 100;
             sprite.y = 100;
             // ...
         }
     } else if (component.status == Component.Error) {
         // Error Handling
         console.log("Error loading component:", component.errorString());
     }
 }

 component = Qt.createComponent("Sprite.qml");
 if (component.status == Component.Ready)
     finishCreation();
 else
     component.statusChanged.connect(finishCreation);

If you are certain the files will be local, you could simplify to:

 component = Qt.createComponent("Sprite.qml");
 sprite = component.createObject(appWindow);

 if (sprite == null) {
     // Error Handling
     console.log("Error loading component:", component.errorString());
 } else {
     sprite.x = 100;
     sprite.y = 100;
     // ...
 }

Notice that once a Sprite object is created, its parent is set to appWindow (defined in main.qml). After creating an item, you must set its parent to an item within the scene. Otherwise your dynamically created item will not appear in the scene.

When using files with relative paths, the path should be relative to the file where Qt.createComponent() is executed.

If the QML component does not exist until runtime, you can create a QML item from a string of QML using the Qt.createQmlObject() function, as in the following example:

 newObject = Qt.createQmlObject('import Qt 4.7; Rectangle {color: "red"; width: 20; height: 20}',
     parentItem, "dynamicSnippet1");

The first argument is the string of QML to create. Just like in a new file, you will need to import any types you wish to use. For importing files with relative paths, the path should be relative to the file where the item in the second argument is defined. Remember to set the parent after creating the item. The second argument is another item in the scene, and the new item is created in the same QML Context as this item. The third argument is the file path associated with this item, which is used for error reporting.

Maintaining Dynamically Created Objects

When managing dynamically created items, you must ensure the creation context outlives the created item. Otherwise, if the creation context is destroyed first, the bindings in the dynamic item will no longer work.

The actual creation context depends on how an item is created:

Also, note that while dynamically created objects may be used the same as other objects, they do not have an id in QML.

Deleting Objects Dynamically

In many user interfaces, it is sufficient to set an item's opacity to 0 or to move the item off the screen instead of deleting the item. If you have lots of dynamically created items, however, you may receive a worthwhile performance benefit if unused items are deleted.

Note that you should never manually delete items that were dynamically created by QML elements (such as Loader). Also, you should generally avoid deleting items that you did not dynamically create yourself.

Items can be deleted using the destroy() method. This method has an optional argument (which defaults to 0) that specifies the approximate delay in milliseconds before the object is to be destroyed. This allows you to wait until the completion of an animation or transition. An example:

 Rectangle {
     id: rootItem
     width: 300
     height: 300

     Component {
         id: rectComponent

         Rectangle {
             id: rect
             width: 40; height: 40;
             color: "red"

             NumberAnimation on opacity { from: 1; to: 0; duration: 1000 }

             Component.onCompleted: rect.destroy(1000);
         }
     }

     function createRectangle() {
         var object = rectComponent.createObject(rootItem);
     }

     Component.onCompleted: createRectangle()
 }

Here, Rectangle objects are destroyed one second after they are created, which is long enough for the NumberAnimation to be played before the object is destroyed.

X