Dynamische Erstellung von QML-Objekten aus JavaScript
QML unterstützt die dynamische Erstellung von Objekten aus JavaScript heraus. Dies ist nützlich, um die Instanziierung von Objekten bis zum tatsächlichen Bedarf zu verzögern und so die Startzeit der Anwendung zu verbessern. Außerdem ermöglicht es die dynamische Erstellung visueller Objekte und deren Hinzufügung zur Szene als Reaktion auf Benutzereingaben oder andere Ereignisse.
Warnung: Objekte sollten nicht dynamisch aus nicht vertrauenswürdigen Quellen erstellt werden. Die Einschränkungen für statische QML-Quellen gelten gleichermaßen für die dynamische Objekterstellung.
Objekte dynamisch erstellen
Es gibt zwei Möglichkeiten, Objekte dynamisch aus JavaScript heraus zu erstellen. Sie können entweder ` Qt.createComponent()` aufrufen, um ein ` Component `-Objekt dynamisch zu erstellen, oder ` Qt.createQmlObject()` verwenden, um ein Objekt aus einer QML-Zeichenkette zu erstellen. Das Erstellen einer Komponente ist die bessere Wahl, wenn Sie bereits eine in einem QML-Dokument definierte Komponente haben und dynamisch Instanzen dieser Komponente erstellen möchten. Andernfalls ist das Erstellen eines Objekts aus einem QML-String sinnvoll, wenn das QML der Komponente selbst zur Laufzeit generiert wird.
Dynamisches Erstellen einer Komponente
Um eine in einer QML-Datei definierte Komponente dynamisch zu laden, rufen Sie die Funktion ` Qt.createComponent()` im ` Qt object` auf. Diese Funktion nimmt die URL der QML-Datei als einziges Argument entgegen und erstellt aus dieser URL ein ` Component `-Objekt.
Sobald Sie über ein ` Component` verfügen, können Sie dessen Methode ` createObject()` aufrufen, um eine Instanz der Komponente zu erstellen. Diese Funktion kann ein oder zwei Argumente entgegennehmen:
- Das erste ist das übergeordnete Objekt für das neue Objekt. Das übergeordnete Objekt kann ein grafisches Objekt (d. h. vom Typ ` Item `) oder ein nicht-grafisches Objekt (d. h. vom Typ ` QtObject ` oder C++ ` QObject `) sein. Nur grafische Objekte mit grafischen übergeordneten Objekten werden auf der Qt Quick visuellen Arbeitsfläche gerendert. Wenn Sie das übergeordnete Objekt später festlegen möchten, können Sie dieser Funktion bedenkenlos „
null“ übergeben. - Das zweite Argument ist optional und stellt eine Zuordnung von Eigenschaft-Wert-Paaren dar, die die anfänglichen Werte aller Eigenschaften des Objekts definieren. Die durch dieses Argument angegebenen Eigenschaftswerte werden auf das Objekt angewendet, bevor dessen Erstellung abgeschlossen ist. Dadurch werden Bindungsfehler vermieden, die auftreten können, wenn bestimmte Eigenschaften initialisiert werden müssen, um andere Eigenschaftsbindungen zu ermöglichen. Zudem ergeben sich im Vergleich zur Definition von Eigenschaftswerten und Bindungen nach der Erstellung des Objekts geringe Leistungsvorteile.
Hier ist ein Beispiel. Zunächst gibt es die Datei „ Sprite.qml “, die eine einfache QML-Komponente definiert:
import QtQuick
Rectangle { width: 80; height: 50; color: "red" }Unsere Hauptanwendungsdatei, „ main.qml “, importiert eine JavaScript-Datei namens „ componentCreation.js “, die „ Sprite “-Objekte erstellt:
import QtQuick
import "componentCreation.js" as MyScript
Rectangle {
id: appWindow
width: 300; height: 300
Component.onCompleted: MyScript.createSpriteObjects();
}Hier ist „ componentCreation.js “. Beachten Sie, dass hier geprüft wird, ob die Komponente „ status “ bereits ein „ Component.Ready “-Objekt ist, bevor „ createObject()“ aufgerufen wird – für den Fall, dass die QML-Datei über das Netzwerk geladen wird und daher nicht sofort verfügbar ist.
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());
}
}Wenn Sie sicher sind, dass es sich bei der zu ladenden QML-Datei um eine lokale Datei handelt, können Sie die Funktion ` finishCreation() ` weglassen und ` createObject()` sofort aufrufen:
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");
}
}Beachten Sie, dass in beiden Fällen ` createObject()` mit ` appWindow ` als übergeordnetem Argument aufgerufen wird, da es sich bei dem dynamisch erstellten Objekt um ein visuelles Objekt (Qt Quick) handelt. Das erstellte Objekt wird zu einem untergeordneten Element des ` appWindow `-Objekts in ` main.qml` und erscheint in der Szene.
Bei der Verwendung von Dateien mit relativen Pfaden sollte der Pfad relativ zu der Datei sein, in der „ Qt.createComponent()“ ausgeführt wird.
Um Signale an dynamisch erstellte Objekte anzuschließen (oder Signale von diesen zu empfangen), verwenden Sie die Methode ` connect() `. Weitere Informationen finden Sie unter „Signale an Methoden und Signale anschließen “.
Es ist auch möglich, Komponenten über die Funktion ` incubateObject()` ohne Blockierung zu instanziieren.
Erstellen eines Objekts aus einer QML-Zeichenkette
Warnung: Das Erstellen von Objekten aus einer QML-Zeichenkette ist extrem langsam, da die Engine die übergebene QML-Zeichenkette bei jedem Vorgang neu kompilieren muss. Außerdem kann es beim programmgesteuerten Erstellen von QML-Code sehr leicht zu ungültigem QML kommen. Es ist weitaus besser, Ihre QML-Komponenten als separate Dateien zu speichern und Eigenschaften sowie Methoden hinzuzufügen, um ihr Verhalten anzupassen, als neue Komponenten durch Zeichenfolgenmanipulation zu erzeugen.
Wenn der QML-Code erst zur Laufzeit definiert wird, können Sie mit der Funktion ` Qt.createQmlObject()` ein QML-Objekt aus einer QML-Zeichenkette erstellen, wie im folgenden Beispiel gezeigt:
const newObject = Qt.createQmlObject(`
import QtQuick
Rectangle {
color: "red"
width: 20
height: 20
}
`,
parentItem,
"myDynamicSnippet"
);Das erste Argument ist die zu erstellende QML-Zeichenkette. Genau wie in einer neuen Datei musst du alle Typen importieren, die du verwenden möchtest. Das zweite Argument ist das übergeordnete Objekt für das neue Objekt, und die Semantik des „parent“-Arguments, die für Komponenten gilt, ist in ähnlicher Weise auch für ` createQmlObject()` anwendbar. Das dritte Argument ist der Dateipfad, der dem neuen Objekt zugeordnet werden soll; dieser wird für die Fehlermeldung verwendet.
Wenn die QML-Zeichenkette Dateien über relative Pfade importiert, sollte der Pfad relativ zu der Datei sein, in der das übergeordnete Objekt (das zweite Argument der Methode) definiert ist.
Wichtig: Beim Erstellen statischer QML-Anwendungen werden QML-Dateien nach Importabhängigkeiten durchsucht. Auf diese Weise werden alle erforderlichen Plugins und Ressourcen bereits zur Kompilierungszeit aufgelöst. Es werden jedoch nur explizite Importanweisungen berücksichtigt (d. h. solche, die am Anfang einer QML-Datei stehen), nicht jedoch Importanweisungen, die in String-Literalen enthalten sind. Um statische Builds zu unterstützen, müssen Sie daher sicherstellen, dass QML-Dateien, die ` Qt.createQmlObject()` verwenden, alle erforderlichen Importe zusätzlich zu denen in den String-Literalen explizit am Anfang der Datei enthalten.
Verwaltung dynamisch erstellter Objekte
Bei der Verwaltung dynamisch erstellter Objekte müssen Sie sicherstellen, dass der Erstellungs-Kontext länger besteht als das erstellte Objekt. Andernfalls, wenn der Erstellungs-Kontext zuerst zerstört wird, funktionieren die Bindungen und Signal-Handler im dynamischen Objekt nicht mehr.
Der tatsächliche Erstellungs-Kontext hängt davon ab, wie ein Objekt erstellt wird:
- Wird ` Qt.createComponent()` verwendet, ist der Erstellungs-Kontext das ` QQmlContext `, in dem diese Methode aufgerufen wird
- Wird ` Qt.createQmlObject()` aufgerufen, ist der Erstellungs-Kontext der Kontext des übergeordneten Objekts, das an diese Methode übergeben wurde
- Wenn ein `
Component{}`-Objekt definiert ist und ` createObject()` oder ` incubateObject()` für dieses Objekt aufgerufen wird, ist der Erstellungs-Kontext der Kontext, in dem das `Component` definiert ist
Beachten Sie außerdem, dass dynamisch erstellte Objekte zwar genauso wie andere Objekte verwendet werden können, in QML jedoch keine ID besitzen.
Objekte dynamisch löschen
In vielen Benutzeroberflächen reicht es aus, die Deckkraft eines visuellen Objekts auf 0 zu setzen oder das visuelle Objekt vom Bildschirm zu verschieben, anstatt es zu löschen. Wenn Sie jedoch viele dynamisch erstellte Objekte haben, können Sie einen nennenswerten Leistungsvorteil erzielen, wenn nicht verwendete Objekte gelöscht werden.
Beachten Sie, dass Sie Objekte, die dynamisch durch QML-Objektfabriken (wie z. B. ` Loader ` und ` Repeater`) erstellt wurden, niemals manuell löschen sollten. Außerdem sollten Sie es vermeiden, Objekte zu löschen, die Sie nicht selbst dynamisch erstellt haben.
Elemente können mithilfe der Methode ` destroy() ` gelöscht werden. Diese Methode verfügt über ein optionales Argument (Standardwert: 0), das die ungefähre Verzögerung in Millisekunden angibt, bevor das Objekt zerstört werden soll.
Hier ist ein Beispiel. Die Methode „ application.qml “ erstellt fünf Instanzen der Komponente „ SelfDestroyingRect.qml “. Jede Instanz führt eine „ NumberAnimation “ aus und ruft nach Abschluss der Animation „ destroy() “ auf ihrem Root-Objekt auf, um sich selbst zu zerstören:
application.qml | |
SelfDestroyingRect.qml | |
Alternativ hätte der „ application.qml “ das erstellte Objekt auch durch den Aufruf von „ object.destroy() “ zerstören können.
Beachten Sie, dass es unbedenklich ist, `destroy()` für ein Objekt innerhalb dieses Objekts aufzurufen. Objekte werden nicht sofort beim Aufruf von `destroy()` zerstört, sondern irgendwann zwischen dem Ende dieses Skriptblocks und dem nächsten Frame bereinigt (es sei denn, Sie haben eine Verzögerung ungleich Null angegeben).
Beachten Sie außerdem, dass, wenn eine ` SelfDestroyingRect `-Instanz statisch wie folgt erstellt wurde:
Item {
SelfDestroyingRect {
// ...
}
}Dies würde zu einem Fehler führen, da Objekte nur dann dynamisch zerstört werden können, wenn sie dynamisch erstellt wurden.
Mit ` Qt.createQmlObject()` erstellte Objekte können auf ähnliche Weise mit ` destroy()` zerstört werden:
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.