![]() |
Home · All Classes · All Functions · Overviews |
QML has some support for dynamically loading and managing QML objects from within Javascript blocks. It is preferable to use the existing QML elements for dynamic object management wherever possible; these are Loader, Repeater, ListView, GridView and PathView. It is also possible to dynamically create and manage objects from C++, and this is preferable for hybrid QML/C++ applications - see Using QML in C++ Applications. Dynamically creating and managing objects from within Javascript blocks is intended for when none of the existing QML elements fit the needs of your application, and you do not desire for your application to involve C++ code.
There are two ways of creating objects dynamically. You can either create a component which instantiates items, or create an item from a string of QML. Creating a component is better for the situation where you have a predefined item which you want to manage dynamic instances of, and creating an item from a string of QML is intended for when the QML itself is generated at runtime.
If you have a component specified in a QML file, you can dynamically load it with the 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.
You can also create a component by placing your QML inside a Component element. Referencing that component element by id will be the same as referencing the variable which you save the result of createComponent into.
Once you have a component you can use its createObject method to create an instance of the component. Example QML script is below. 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.isReady()){ sprite = component.createObject(); if(sprite == 0){ // Error Handling }else{ sprite.parent = page; sprite.x = 200; //... } }else if(component.isError()){ // Error Handling } } component = createComponent("Sprite.qml"); if(component.isReady()){ finishCreation(); }else{ component.statusChanged.connect(finishCreation); }
If you are certain the files will be local, you could simplify to
component = createComponent("Sprite.qml"); sprite = component.createObject(); if(sprite == 0){ // Error Handling console.log(component.errorsString()); }else{ sprite.parent = page; sprite.x = 200; //... }
After creating the item, remember to 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 createComponent is executed.
If the QML does not exist until runtime, you can create a QML item from a string of QML using the createQmlObject function, as in the following example:
newObject = createQmlObject('import Qt 4.6; Rectangle {color: "red"; width: 20; height: 20}', targetItem, "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.
Dynamically created objects may be used the same as other objects, however they will not have an id in QML.
A restriction which you need to manage with dynamically created items, is that the creation context must outlive the created item. The creation context is the QDeclarativeContext in which createComponent was called, or the context in which the Component element, or the item used as the second argument to createQmlObject, was specified. If the creation context is destroyed before the dynamic item is, then bindings in the dynamic item will fail to work.
You should generally avoid dynamically deleting objects that you did not dynamically create. In many UIs, it is sufficient to set the opacity to 0 or to move the item off of the edge of the screen. If you have lots of dynamically created items however, deleting them when they are no longer used will provide a worthwhile performance benefit. Note that you should never manually delete items which were dynamically created by QML Elements such as Loader.
To manually delete a QML item, call its destroy method. This method has one argument, which is an approximate delay in ms and which defaults to zero. This allows you to wait until the completion of an animation or transition. An example:
Component{ id:fadesOut Rectangle{ id: rect width: 40; height: 40; opacity: NumberAnimation{from:1; to:0; duration: 1000;} Component.onCompleted: rect.destroy(1000); } } function createFadesOut(parentItem) { var object = fadesOut.createObject(); object.parent = parentItem; }
In the above example, the dynamically created rectangle calls destroy as soon as it's created, but delays long enough for its fade out animation to play.
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) | Trademarks | Qt 4.7.0 |