Création dynamique d'objets QML à partir de JavaScript
QML prend en charge la création dynamique d'objets à partir de JavaScript. Cela permet de retarder l'instanciation des objets jusqu'à ce qu'elle soit nécessaire, améliorant ainsi le temps de démarrage de l'application. Elle permet également de créer dynamiquement des objets visuels et de les ajouter à la scène en réaction à la saisie de l'utilisateur ou à d'autres événements.
Création dynamique d'objets
Il existe deux façons de créer des objets dynamiquement à partir de JavaScript. Vous pouvez soit appeler Qt.createComponent() pour créer dynamiquement un objet Component, soit utiliser Qt.createQmlObject() pour créer un objet à partir d'une chaîne de caractères QML. La création d'un composant est préférable si vous avez un composant existant défini dans un document QML et que vous souhaitez créer dynamiquement des instances de ce composant. Sinon, la création d'un objet à partir d'une chaîne de QML est utile lorsque l'objet QML lui-même est généré à l'exécution.
Création dynamique d'un composant
Pour charger dynamiquement un composant défini dans un fichier QML, appelez la fonction Qt.createComponent() dans le fichier Qt object. Cette fonction prend l'URL du fichier QML comme seul argument et crée un objet Component à partir de cette URL.
Une fois que vous avez un objet Component, vous pouvez appeler sa méthode createObject() pour créer une instance du composant. Cette fonction peut prendre un ou deux arguments :
- Le premier est le parent du nouvel objet. Le parent peut être un objet graphique (c'est-à-dire de type Item ) ou un objet non graphique (c'est-à-dire de type QtObject ou C++ QObject ). Seuls les objets graphiques avec des objets parents graphiques seront rendus sur la toile visuelle. Qt Quick toile visuelle. Si vous souhaitez définir le parent ultérieurement, vous pouvez passer
nullà cette fonction en toute sécurité. - Le deuxième argument est facultatif et est une carte de paires propriété-valeur qui définissent les valeurs initiales de toutes les propriétés de l'objet. Les valeurs de propriété spécifiées par cet argument sont appliquées à l'objet avant que sa création ne soit finalisée, ce qui permet d'éviter les erreurs de liaison qui peuvent se produire si des propriétés particulières doivent être initialisées pour permettre d'autres liaisons de propriété. En outre, les performances sont légèrement améliorées par rapport à la définition des valeurs de propriété et des liaisons après la création de l'objet.
Voici un exemple. Tout d'abord, nous avons Sprite.qml, qui définit un composant QML simple :
import QtQuick Rectangle { width: 80; height: 50; color: "red" }
Notre fichier d'application principal, main.qml, importe un fichier JavaScript componentCreation.js qui créera des objets Sprite:
import QtQuick import "componentCreation.js" as MyScript Rectangle { id: appWindow width: 300; height: 300 Component.onCompleted: MyScript.createSpriteObjects(); }
Voici componentCreation.js. Remarquez qu'il vérifie si le composant status est Component.Ready avant d'appeler createObject() au cas où le fichier QML serait chargé via un réseau et ne serait donc pas prêt immédiatement.
var component;
var sprite;
function createSpriteObjects() {
component = Qt.createComponent("Sprite.qml");
if (component.status == Component.Ready)
finishCreation();
else
component.statusChanged.connect(finishCreation);
}
function finishCreation() {
if (component.status == Component.Ready) {
sprite = component.createObject(appWindow, {x: 100, y: 100});
if (sprite == null) {
// Error Handling
console.log("Error creating object");
}
} else if (component.status == Component.Error) {
// Error Handling
console.log("Error loading component:", component.errorString());
}
}Si vous êtes certain que le fichier QML à charger est un fichier local, vous pouvez omettre la fonction finishCreation() et appeler createObject() immédiatement :
function createSpriteObjects() {
component = Qt.createComponent("Sprite.qml");
sprite = component.createObject(appWindow, {x: 100, y: 100});
if (sprite == null) {
// Error Handling
console.log("Error creating object");
}
}Remarquez que dans les deux cas, createObject() est appelé avec appWindow comme argument parent, puisque l'objet créé dynamiquement est un objet visuel (Qt Quick). L'objet créé deviendra un enfant de l'objet appWindow dans main.qml, et apparaîtra dans la scène.
Lors de l'utilisation de fichiers avec des chemins relatifs, le chemin doit être relatif au fichier dans lequel Qt.createComponent() est exécuté.
Pour connecter des signaux à des objets créés dynamiquement (ou recevoir des signaux de ces objets), utilisez la méthode signal connect(). Pour plus d'informations, voir Connecter des signaux aux méthodes et aux signaux.
Il est également possible d'instancier des composants sans blocage via la fonction incubateObject().
Création d'un objet à partir d'une chaîne de caractères QML
Attention : La création d'objets à partir d'une chaîne de QML est extrêmement lente car le moteur doit compiler la chaîne QML passée à chaque fois. De plus, il est très facile de produire du QML invalide lors de la construction programmatique du code QML. Il est préférable de conserver vos composants QML dans des fichiers séparés et d'ajouter des propriétés et des méthodes pour personnaliser leur comportement plutôt que de produire de nouveaux composants en manipulant des chaînes de caractères.
Si le QML n'est défini qu'au moment de l'exécution, vous pouvez créer un objet QML à partir d'une chaîne de QML en utilisant la fonction Qt.createQmlObject(), comme dans l'exemple suivant :
const newObject = Qt.createQmlObject(` import QtQuick Rectangle { color: "red" width: 20 height: 20 } `, parentItem, "myDynamicSnippet" );
Le premier argument est la chaîne de QML à créer. Comme dans un nouveau fichier, vous devrez importer tous les types que vous souhaitez utiliser. Le deuxième argument est l'objet parent du nouvel objet, et la sémantique de l'argument parent qui s'applique aux composants s'applique également à createQmlObject(). Le troisième argument est le chemin d'accès au fichier à associer au nouvel objet ; il est utilisé pour les rapports d'erreur.
Si la chaîne de QML importe des fichiers en utilisant des chemins relatifs, le chemin doit être relatif au fichier dans lequel l'objet parent (le deuxième argument de la méthode) est défini.
Important : lors de la création d'applications QML statiques, les fichiers QML sont analysés pour détecter les dépendances d'importation. Ainsi, tous les plugins et ressources nécessaires sont résolus au moment de la compilation. Toutefois, seules les déclarations d'importation explicites sont prises en compte (celles qui se trouvent au début d'un fichier QML), et non les déclarations d'importation incluses dans des chaînes de caractères littérales. Pour prendre en charge les constructions statiques, vous devez donc vous assurer que les fichiers QML utilisant Qt.createQmlObject() contiennent explicitement toutes les importations nécessaires au début du fichier, en plus de celles contenues dans les chaînes de caractères.
Gestion des objets créés dynamiquement
Lorsque vous gérez des objets créés dynamiquement, vous devez vous assurer que le contexte de création survit à l'objet créé. Sinon, si le contexte de création est détruit en premier, les liaisons et les gestionnaires de signaux de l'objet dynamique ne fonctionneront plus.
Le contexte de création réel dépend de la manière dont l'objet est créé :
- Si Qt.createComponent() est utilisé, le contexte de création est le QQmlContext dans lequel cette méthode est appelée
- Si Qt.createQmlObject() est appelé, le contexte de création est le contexte de l'objet parent passé à cette méthode.
- Si un objet
Component{}est défini et que createObject() ou incubateObject() est appelé sur cet objet, le contexte de création est le contexte dans lequelComponentest défini.
Notez également que si les objets créés dynamiquement peuvent être utilisés de la même manière que les autres objets, ils n'ont pas d'identifiant en QML.
Suppression dynamique d'objets
Dans de nombreuses interfaces utilisateur, il suffit de régler l'opacité d'un objet visuel sur 0 ou de déplacer l'objet visuel hors de l'écran au lieu de le supprimer. Cependant, si vous avez beaucoup d'objets créés dynamiquement, la suppression des objets inutilisés peut s'avérer bénéfique en termes de performances.
Notez que vous ne devez jamais supprimer manuellement des objets qui ont été créés dynamiquement par des usines d'objets QML de commodité (telles que Loader et Repeater). De même, vous devez éviter de supprimer des objets que vous n'avez pas créés dynamiquement vous-même.
Les éléments peuvent être supprimés à l'aide de la méthode destroy(). Cette méthode comporte un argument facultatif (dont la valeur par défaut est 0) qui spécifie le délai approximatif en millisecondes avant la destruction de l'objet.
Voici un exemple. Le site application.qml crée cinq instances du composant SelfDestroyingRect.qml. Chaque instance exécute une animation NumberAnimation et, une fois l'animation terminée, appelle destroy() sur son objet racine pour s'autodétruire :
application.qml | import QtQuick Item { id: container width: 500; height: 100 Component.onCompleted: { var component = Qt.createComponent("SelfDestroyingRect.qml"); for (var i=0; i<5; i++) { var object = component.createObject(container); object.x = (object.width + 10) * i; } } } |
SelfDestroyingRect.qml | import QtQuick Rectangle { id: rect width: 80; height: 80 color: "red" NumberAnimation on opacity { to: 0 duration: 1000 onRunningChanged: { if (!running) { console.log("Destroying...") rect.destroy(); } } } } |
Le application.qml aurait également pu détruire l'objet créé en appelant le object.destroy().
Notez qu'il n'est pas dangereux d'appeler destroy() sur un objet à l'intérieur de cet objet. Les objets ne sont pas détruits au moment où destroy() est appelé, mais sont nettoyés entre la fin du bloc de script et l'image suivante (à moins que vous n'ayez spécifié un délai différent de zéro).
Notez également que si une instance de SelfDestroyingRect était créée statiquement comme ceci :
Item { SelfDestroyingRect { // ... } }
Il en résulterait une erreur, car les objets ne peuvent être détruits dynamiquement que s'ils ont été créés dynamiquement.
Les objets créés à l'aide de Qt.createQmlObject() peuvent également être détruits à l'aide de destroy():
const newObject = Qt.createQmlObject(` import QtQuick Rectangle { color: "red" width: 20 height: 20 } `, parentItem, "myDynamicSnippet" ); newObject.destroy(1000);
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.