Auf dieser Seite

Aufbau eines QML-Dokuments

Ein QML-Dokument ist ein in sich geschlossener Abschnitt von QML-Quellcode, der aus drei Teilen besteht:

  • Eine optionale Liste von Pragmas
  • seiner Import -Anweisungen
  • Eine einzige Deklaration des Wurzelobjekts

Gemäß Konvention trennt eine einzelne Leerzeile die Importe von der Definition der Objekthierarchie.

QML-Dokumente werden immer im UTF-8-Format kodiert.

Pragmas

Pragmas sind Anweisungen an die QML-Engine selbst, mit denen bestimmte Eigenschaften von Objekten in der aktuellen Datei festgelegt oder die Art und Weise, wie die Engine den Code interpretiert, geändert werden können. Die folgenden Pragmas werden im Folgenden ausführlich erläutert.

pragmaWerteStandardwertseit
Singleton5.2
ListPropertyAssignBehaviorAnhängenX6.3
Ersetzen6.3
Ersetzen, wenn nicht Standard6.3
KomponentenverhaltenGebunden6.4
UngebundenX6.4
Verhalten der FunktionssignaturIgnoriert6.5
ErzwungenX6.5
NativeMethodBehaviorAcceptThisObject6,5
RejectThisObjectX6,5
Verhalten des WerttypsReferenzX6.5
Kopieren6.5
Adressierbar6,6
Nicht adressierbarX6.6
Assertierbar6.8
Übersetzer<Übersetzungskontext><Dateiname>6,7

Singleton

pragma Singleton Deklariert die an der Wurzel des QML-Dokuments definierte Komponente als Singleton. Weitere Informationen finden Sie unter „Singletons in QML “.

ListPropertyAssignBehavior

Mit diesem Pragma können Sie festlegen, wie Zuweisungen an Listen-Eigenschaften in den im QML-Dokument definierten Komponenten behandelt werden sollen. Standardmäßig wird bei der Zuweisung an eine Listen-Eigenschaft der Wert an das Ende der Liste angehängt. Sie können dieses Verhalten explizit mit dem Wert „ Append “ festlegen. Alternativ können Sie festlegen, dass der Inhalt von Listen-Eigenschaften immer ersetzt wird („ Replace “) oder nur dann ersetzt wird, wenn es sich nicht um die Standardeigenschaft handelt („ ReplaceIfNotDefault “).

Betrachten Sie einen Basistyp im Dokument „Base.qml“:

pragma ListPropertyAssignBehavior: ReplaceIfNotDefault
import QtQuick

Item {
    objectName: "outer"

    default property list<Item> d: [
        Item { objectName: "inner" }
    ]

    property list<Item> notDefault: [
        Item { objectName: "one" }
    ]
}

Wenn Sie dann von „Base“ ableiten und dessen Listen-Eigenschaften ändern, greift das „ListPropertyAssignBehavior“ in Kraft. In diesem Fall gilt:

Base {
    // The new item is appended to the list even though you're assigning.
    // The (default) property "d" now contains "inner" and "inner2".
    d: [
        Item { objectName: "inner2" }
    ]

    // The list is replaced by the list given here.
    // The (non-default) property "notDefault" now contains only "two".
    notDefault: [
        Item { objectName: "two" }
    ]
}

Wenn kein ` ListPropertyAssignBehavior ` angegeben ist oder wenn ` Append ` angegeben ist, wird das Objekt „two“ stattdessen an die Eigenschaft ` notDefault ` angehängt, was zu einer Liste führt, die sowohl „one“ als auch „two“ enthält.

Wird „ Replace “ angegeben, wird auch der Inhalt der Standard-Eigenschaft „d“ ersetzt, was zu einer Liste führt, die nur „inner2“ enthält.

Hinweis: Die gleiche Deklaration kann auch für in C++ definierte Typen verwendet werden, indem die Makros „ QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND “, „ QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE “ und „ QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT “ zur Klassendeklaration hinzugefügt werden. Zum Beispiel:

class MyType : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE

    Q_PROPERTY(QQmlListProperty<QObject> a READ a)
    [...]
};

ComponentBehavior

In derselben QML-Datei können mehrere Komponenten definiert sein. Der oberste Bereich der QML-Datei ist eine Komponente, und zusätzlich können Elemente vom Typ „ QQmlComponent “ vorhanden sein, die explizit oder implizit als Eigenschaften oder Inline-Komponenten erstellt wurden. Diese Komponenten sind verschachtelt. Jede der inneren Komponenten befindet sich innerhalb einer bestimmten äußeren Komponente. In den meisten Fällen sind IDs, die in einer äußeren Komponente definiert sind, innerhalb aller ihrer verschachtelten inneren Komponenten zugänglich. Sie können jedoch Elemente aus einer Komponente in einem beliebigen anderen Kontext erstellen, in dem andere IDs verfügbar sind. Dadurch wird die Annahme widerlegt, dass äußere IDs verfügbar sind. Daher können die Engine und die QML-Tools im Allgemeinen nicht im Voraus wissen, auf welchen Typ – falls überhaupt – solche IDs zur Laufzeit aufgelöst werden.

Mit dem Pragma `ComponentBehavior` können Sie alle in einer Datei definierten inneren Komponenten so einschränken, dass sie Objekte nur innerhalb ihres ursprünglichen Kontexts erstellen. Ist eine Komponente an ihren Kontext gebunden, können Sie IDs aus äußeren Komponenten derselben Datei innerhalb der Komponente sicher verwenden. Die QML-Entwicklungswerkzeuge gehen dann davon aus, dass die äußeren IDs mit ihren spezifischen Typen verfügbar sind.

Um die Komponenten an ihren Kontext zu binden, geben Sie das Argument „ Bound “ an:

pragma ComponentBehavior: Bound

Dies bedeutet, dass bei Namenskonflikten IDs, die außerhalb einer gebundenen Komponente definiert sind, lokale Eigenschaften von Objekten überschreiben, die aus der Komponente erstellt wurden. Andernfalls wäre die Verwendung der IDs tatsächlich nicht sicher, da spätere Versionen eines Moduls der Komponente möglicherweise weitere Eigenschaften hinzufügen könnten. Ist die Komponente nicht gebunden, überschreiben lokale Eigenschaften IDs, die außerhalb der Komponente definiert sind, jedoch nicht IDs, die innerhalb der Komponente definiert sind.

Das folgende Beispiel gibt die Eigenschaft `r` des Objekts ` ListView ` mit der ID `color` aus, nicht die Eigenschaft `r` der Farbe des Rechtecks.

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 id: color
 property int r: 12
 model: 1

 delegate: Rectangle {
  Component.onCompleted: console.log(color.r)
 }
}

Der Standardwert von ` ComponentBehavior ` lautet ` Unbound`. Sie können ihn auch explizit festlegen. In einer zukünftigen Version von Qt wird der Standardwert auf ` Bound` geändert.

An ihren Kontext gebundene Delegate-Komponenten erhalten bei der Instanziierung keinen eigenen privaten Kontext. Das bedeutet, dass Modelldaten in diesem Fall nur über erforderliche Eigenschaften übergeben werden können. Die Übergabe von Modelldaten über Kontexteigenschaften funktioniert nicht. Dies betrifft Delegates zu z. B. ` Instantiator`, ` Repeater`, ` ListView`, ` TableView`, ` GridView`, ` TreeView ` und generell alles, was intern ` DelegateModel ` verwendet.

Beispielsweise funktioniert Folgendes nicht:

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 delegate: Rectangle {
     color: model.myColor
 }
}

model Die Eigenschaft „ delegate “ von „ ListView “ ist eine Komponente. Daher wird hier implizit ein „ Component “ um die „ Rectangle “ herum erstellt. Diese Komponente ist an ihren Kontext gebunden. Sie erhält nicht die Eigenschaft „context“, die von „ ListView “ bereitgestellt wird. Damit es funktioniert, müsstet ihr es folgendermaßen schreiben:

pragma ComponentBehavior: Bound
import QtQuick

ListView {
 delegate: Rectangle {
     required property color myColor
     color: myColor
 }
}

Sie können Komponenten in einer QML-Datei verschachteln. Das Pragma gilt für alle Komponenten in der Datei, unabhängig davon, wie tief sie verschachtelt sind.

FunctionSignatureBehavior

Mit diesem Pragma können Sie die Art und Weise ändern, wie Typangaben bei Funktionen behandelt werden. Seit Qt 6.7 werden Typangaben beim Aufruf von Funktionen erzwungen. Zuvor hat nur der QML-Skript-Compiler die Typangaben erzwungen. Der Interpreter und der JIT-Compiler haben sie ignoriert. Die konsequente Durchsetzung der Typangaben stellt eine Verhaltensänderung im Vergleich zu früheren Versionen dar, da man zuvor Funktionen mit nicht übereinstimmenden Argumenten aufrufen konnte.

Die Angabe von „ Ignored “ als Wert bewirkt, dass die QML-Engine und der QML-Skript-Compiler alle Typangaben ignorieren und somit das Verhalten des Interpreters und des JIT vor Version 6.7 wiederherstellen. Infolgedessen wird weniger Code vorab in C++ kompiliert, und mehr Code muss interpretiert oder per JIT kompiliert werden.

Die Angabe von „ Enforced “ als Wert legt den Standardwert explizit fest: Typangaben werden immer durchgesetzt.

NativeMethodBehavior

Der Aufruf von C++-Methoden mit „ this “-Objekten, die sich von dem Objekt unterscheiden, aus dem sie abgerufen wurden, funktioniert aus historischen Gründen nicht. Das ursprüngliche Objekt wird als „ this “-Objekt verwendet. Sie können die Verwendung des angegebenen „ this “-Objekts zulassen, indem Sie „ pragma NativeMethodBehavior: AcceptThisObject “ setzen. Die Angabe von „ RejectThisObject “ behält das historische Verhalten bei.

Ein Beispiel hierfür finden Sie unter „C++-Methoden und das ‚this‘-Objekt“.

ValueTypeBehavior

Mit diesem Pragma können Sie die Art und Weise ändern, wie Werttypen und Sequenzen behandelt werden.

Normalerweise dürfen Namen in Kleinbuchstaben im JavaScript-Code keine Typnamen sein. Dies stellt ein Problem dar, da die Namen von Werttypen in Kleinbuchstaben geschrieben sind. Sie können „ Addressable “ als Wert für dieses Pragma angeben, um dies zu ändern. Wenn „ Addressable “ angegeben ist, kann ein JavaScript-Wert explizit in einen bestimmten, benannten Werttyp umgewandelt werden. Dies geschieht mithilfe des Operators „ as “, so wie Sie es bei Objekttypen tun würden. Darüber hinaus können Sie auch mithilfe des Operators „ instanceof “ auf Werttypen prüfen:

pragma ValueTypeBehavior: Addressable
import QtQml

QtObject {
 property var a
 property real b: (a as rect).x
 property bool c: a instanceof rect

 property var rect // inaccessible. "rect" is a type name.
}

Da „ rect “ im obigen Beispiel nun ein Typname ist, überschreibt er alle Eigenschaften mit dem Namen „ rect “.

Das explizite Umwandeln in den gewünschten Typ unterstützt die Tool-Nutzung. Dadurch kann der Qt Quick -Compiler effizienten Code generieren, was ihm andernfalls nicht möglich wäre. Mit qmllint können Sie solche Vorkommen aufspüren.

Es gibt außerdem einen Wert für „ Inaddressable “, mit dem Sie das Standardverhalten explizit festlegen können.

Ein weiteres Attribut des Pragmas „ ValueTypeBehavior “ ist „ Assertable “, das in Qt 6.8 eingeführt wurde. Aufgrund eines Fehlers in Qt 6.6 und 6.7 prüft die obige Typüberprüfung „ a as rect “ nicht nur, ob „ a “ ein „ rect “ ist, sondern konstruiert auch ein „ rect “, wenn „ a “ von einem kompatiblen Typ ist. Dies entspricht offensichtlich nicht dem Zweck einer Typüberprüfung. Die Angabe von „ Assertable “ verhindert dieses Verhalten und beschränkt Typüberprüfungen für Werttypen darauf, lediglich den Typ zu prüfen. Sie sollten dies immer angeben, wenn Sie Werttypen mit „ as “ verwenden möchten. In jedem Fall ist das Ergebnis „ undefined “, wenn die Typüberprüfung für einen Werttyp fehlschlägt.

instanceof hat dieses Problem nicht, da es nur auf Vererbung prüft und nicht auf alle möglichen Typumwandlungen.

Hinweis: Die Verwendung von ` as ` mit den Typen ` int ` und ` double ` ist nicht ratsam, da nach den Regeln von JavaScript das Ergebnis jeder Berechnung eine Gleitkommazahl ist, selbst wenn es zufällig denselben Wert wie sein ganzzahliges Äquivalent hat. Umgekehrt ist jede ganzzahlige Konstante, die Sie in JavaScript deklarieren, gemäß den Typzuordnungsregeln von QML kein `double`. Darüber hinaus sind ` int ` und ` double ` reservierte Wörter. Sie können diese Typen nur über Typ-Namespaces adressieren.

Werttypen und Sequenzen werden im Allgemeinen als Referenzen behandelt. Das bedeutet: Wenn Sie eine Instanz eines Werttyps aus einer Eigenschaft in einen lokalen Wert abrufen und anschließend den lokalen Wert ändern, wird auch die ursprüngliche Eigenschaft geändert. Wenn Sie die ursprüngliche Eigenschaft explizit schreiben, wird zudem der lokale Wert aktualisiert. Dieses Verhalten ist an vielen Stellen eher unintuitiv, und Sie sollten sich nicht darauf verlassen. Die Werte „ Copy “ und „ Reference “ für das Pragma „ ValueTypeBehavior “ sind experimentelle Optionen, um dieses Verhalten zu ändern. Sie sollten sie nicht verwenden. Die Angabe von „ Copy “ bewirkt, dass alle Werttypen als tatsächliche Kopien behandelt werden. Die Angabe von „ Reference “ legt das Standardverhalten explizit fest.

Anstatt „ Copy “ zu verwenden, sollten Sie Referenzen auf Werttypen und Sequenzen jedes Mal explizit neu laden, wenn sie durch Nebeneffekte beeinflusst worden sein könnten. Nebenwirkungen können immer dann auftreten, wenn Sie eine Funktion aufrufen oder eine Eigenschaft imperativ setzen. qmllint bietet hierzu eine Anleitung. Im folgenden Code wird beispielsweise die Variable ` f ` nach dem Schreiben von ` width` von Nebenwirkungen betroffen. Dies liegt daran, dass es möglicherweise eine Bindung in einem abgeleiteten Typ oder in einem ` Binding `-Element gibt, die ` font ` aktualisiert, wenn ` width ` geändert wird.

import QtQuick
Text {
 function a() : real {
     var f = font;
     width = f.pixelSize;
     return f.pointSize;
 }
}

Um dies zu beheben, können Sie vermeiden, f über den Schreibvorgang auf width hinweg zu halten:

import QtQuick
Text {
 function a() : real {
     var f = font;
     width = f.pixelSize;
     f = font;
     return f.pointSize;
 }
}

Dies lässt sich wiederum wie folgt verkürzen:

import QtQuick
Text {
 function a() : real {
     width = font.pixelSize;
     return font.pointSize;
 }
}

Man könnte annehmen, dass das erneute Abrufen der Eigenschaft „ font “ aufwendig ist, doch tatsächlich aktualisiert die QML-Engine Referenzen auf Werttypen automatisch bei jedem Lesezugriff. Dies ist also nicht aufwendiger als die erste Version, sondern eine übersichtlichere Art, dieselben Operationen auszudrücken.

Übersetzer

Mit diesem Pragma können Sie den Kontext für die Übersetzungen in der Datei festlegen.

pragma Translator: myTranslationContext
pragma Translator: "myTranslationContext"

Weitere Informationen zur Internationalisierung mit QML finden Sie unter „Quellcode für die Übersetzung in QML schreiben“.

Importe

Ein Dokument muss die erforderlichen Module oder Typ-Namespaces importieren, damit die Engine die im Dokument referenzierten QML-Objekttypen laden kann. Standardmäßig kann ein Dokument auf alle QML-Objekttypen zugreifen, die über „ .qml “-Dateien im selben Verzeichnis definiert wurden; wenn ein Dokument auf andere Objekttypen verweisen muss, muss es den Typ-Namespace importieren, in dem diese Typen registriert wurden.

Im Gegensatz zu C oder C++ verfügt QML nicht über einen Präprozessor, der das Dokument vor der Übergabe an den „ QML engine “ modifiziert. Die Anweisungen „ import “ kopieren den Code im Dokument nicht und fügen ihn nicht am Anfang ein, sondern weisen die QML-Engine an, wie die im Dokument gefundenen Typverweise aufgelöst werden sollen. Jede in einem QML-Dokument vorhandene Typreferenz – wie beispielsweise ` Rectangle ` und ` ListView ` –, einschließlich derjenigen, die innerhalb eines JavaScript-Blocks oder in Eigenschaftsbindungen vorkommen, wird ausschließlich auf der Grundlage der Importanweisungen aufgelöst. Es muss mindestens eine ` import `-Anweisung vorhanden sein, wie beispielsweise ` import QtQuick 2.0`.

Ausführliche Informationen zu QML-Importen finden Sie in der Dokumentation „QML-Syntax – Importanweisungen “.

Die Deklaration des Wurzelobjekts

Ein QML-Dokument beschreibt eine Hierarchie von Objekten, die instanziiert werden können. Jede Objektdefinition weist eine bestimmte Struktur auf: Sie hat einen Typ, kann eine ID und einen Objektnamen haben, kann Eigenschaften, Methoden, Signale und Signal-Handler enthalten.

Eine QML-Datei darf nur eine einzige Stammobjektdefinition enthalten. Folgendes ist ungültig und führt zu einem Fehler:

// MyQmlFile.qml
import QtQuick 2.0

Rectangle { width: 200; height: 200; color: "red" }
Rectangle { width: 200; height: 200; color: "blue" }    // invalid!

Dies liegt daran, dass eine .qml-Datei automatisch einen QML-Typ definiert, der eine einzelne QML-Objektdefinition kapselt. Dies wird im Abschnitt „Dokumente als QML-Objekttypdefinitionen“ näher erläutert.

Siehe auch Typ-Annotationen und Assertions.

© 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.