QML-Objekt-Attribute

Jeder QML-Objekttyp hat einen definierten Satz von Attributen. Jede Instanz eines Objekttyps wird mit dem Satz von Attributen erstellt, die für diesen Objekttyp definiert wurden. Es gibt verschiedene Arten von Attributen, die spezifiziert werden können und im Folgenden beschrieben werden.

Attribute in Objektdeklarationen

Eine Objektdeklaration in einem QML-Dokument definiert einen neuen Typ. Sie deklariert auch eine Objekthierarchie, die instanziiert wird, wenn eine Instanz dieses neu definierten Typs erstellt wird.

Der Satz von QML-Objekttyp-Attribut-Typen ist wie folgt:

  • das id-Attribut
  • Eigenschaftsattribute
  • Signal-Attribute
  • Signalhandler-Attribute
  • Methoden-Attribute
  • angehängte Eigenschaften und angehängte Signalhandlerattribute
  • Aufzählungsattribute

Diese Attribute werden im Folgenden im Detail besprochen.

Das id-Attribut

Jeder QML-Objekttyp hat genau ein id-Attribut. Dieses Attribut wird von der Sprache selbst bereitgestellt und kann von keinem QML-Objekttyp umdefiniert oder überschrieben werden.

Dem id-Attribut einer Objektinstanz kann ein Wert zugewiesen werden, damit dieses Objekt von anderen Objekten identifiziert und referenziert werden kann. Dieser id muss mit einem Kleinbuchstaben oder einem Unterstrich beginnen und darf keine anderen Zeichen als Buchstaben, Zahlen und Unterstriche enthalten.

Unten sehen Sie ein TextInput Objekt und ein Text Objekt. Der id Wert des TextInput Objekts wird auf "myTextInput" gesetzt. Das Objekt Text setzt seine Eigenschaft text auf denselben Wert wie die Eigenschaft text des Objekts TextInput, indem es auf myTextInput.text verweist. Jetzt zeigen beide Objekte denselben Text an:

import QtQuick

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

Auf ein Objekt kann von überall innerhalb des Komponentenbereichs, in dem es deklariert ist, durch seinen id verwiesen werden. Daher muss ein id Wert innerhalb seines Komponentenbereichs immer eindeutig sein. Weitere Informationen finden Sie unter Bereich und Namensauflösung.

Sobald eine Objektinstanz erstellt ist, kann der Wert des Attributs id nicht mehr geändert werden. Auch wenn es wie eine gewöhnliche Eigenschaft aussieht, ist das id Attribut kein gewöhnliches property Attribut, und es gilt eine besondere Semantik; zum Beispiel ist es im obigen Beispiel nicht möglich, auf myTextInput.id zuzugreifen.

Eigenschaftsattribute

Eine Eigenschaft ist ein Attribut eines Objekts, dem ein statischer Wert zugewiesen oder das an einen dynamischen Ausdruck gebunden werden kann. Der Wert einer Eigenschaft kann von anderen Objekten gelesen werden. Im Allgemeinen kann sie auch von einem anderen Objekt geändert werden, es sei denn, ein bestimmter QML-Typ hat dies für eine bestimmte Eigenschaft ausdrücklich untersagt.

Definieren von Eigenschaftsattributen

Eine Eigenschaft kann für einen Typ in C++ definiert werden, indem eine Q_PROPERTY einer Klasse registriert wird, die dann im QML-Typsystem registriert wird. Alternativ dazu kann eine benutzerdefinierte Eigenschaft eines Objekttyps in einer Objektdeklaration in einem QML-Dokument mit der folgenden Syntax definiert werden:

[default] [required] [readonly] property <propertyType> <propertyName>

Auf diese Weise kann eine Objektdeklaration einen bestimmten Wert für externe Objekte freigeben oder einen internen Zustand leichter aufrechterhalten.

Eigenschaftsnamen müssen mit einem Kleinbuchstaben beginnen und dürfen nur Buchstaben, Zahlen und Unterstriche enthalten. Reservierte Wörter in JavaScript sind keine gültigen Eigenschaftsnamen. Die Schlüsselwörter default, required und readonly sind optional und verändern die Semantik der deklarierten Eigenschaft. In den folgenden Abschnitten über Standardeigenschaften, erforderliche Eigenschaften und schreibgeschützte Eigenschaften finden Sie weitere Informationen über ihre jeweilige Bedeutung.

Die Deklaration einer benutzerdefinierten Eigenschaft erzeugt implizit ein Wertänderungssignal für diese Eigenschaft sowie einen zugehörigen Signalhandler mit dem Namen on<PropertyName>Changed, wobei <PropertyName> der Name der Eigenschaft ist, wobei der erste Buchstabe groß geschrieben wird.

Die folgende Objektdeklaration definiert zum Beispiel einen neuen Typ, der vom Basistyp Rectangle abgeleitet ist. Er hat zwei neue Eigenschaften, wobei für eine dieser neuen Eigenschaften ein Signalhandler implementiert ist:

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}
Gültige Typen in benutzerdefinierten Eigenschaftsdefinitionen

Neben dem Typ enumeration kann jeder der QML-Wertetypen als benutzerdefinierter Eigenschaftstyp verwendet werden. Dies sind zum Beispiel alle gültigen Eigenschaftsdeklarationen:

Item {
    property int someNumber
    property string someString
    property url someUrl
}

(Aufzählungswerte sind einfach ganze Zahlenwerte und können stattdessen mit dem Typ int bezeichnet werden).

Einige Wertetypen werden vom Modul QtQuick bereitgestellt und können daher nicht als Eigenschaftstypen verwendet werden, es sei denn, das Modul wird importiert. Weitere Einzelheiten finden Sie in der Dokumentation zu QML-Wertetypen.

Beachten Sie, dass der Wertetyp var ein allgemeiner Platzhaltertyp ist, der jeden Wertetyp aufnehmen kann, einschließlich Listen und Objekte:

property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }

Außerdem kann jeder QML-Objekttyp als Eigenschaftstyp verwendet werden. Ein Beispiel:

property Item someItem
property Rectangle someRectangle

Dies gilt auch für benutzerdefinierte QML-Typen. Wenn ein QML-Typ in einer Datei mit dem Namen ColorfulButton.qml (in einem Verzeichnis, das dann vom Client importiert wurde) definiert wurde, dann wäre auch eine Eigenschaft vom Typ ColorfulButton gültig.

Zuweisung von Werten zu Eigenschaftsattributen

Der Wert einer Eigenschaft einer Objektinstanz kann auf zwei verschiedene Arten festgelegt werden:

  • eine Wertzuweisung bei der Initialisierung
  • eine imperative Wertzuweisung

In beiden Fällen kann der Wert entweder ein statischer Wert oder ein Wert eines Bindungsausdrucks sein.

Wertzuweisung bei der Initialisierung

Die Syntax für die Zuweisung eines Wertes zu einer Eigenschaft bei der Initialisierung lautet:

<propertyName> : <value>

Eine Initialisierungswertzuweisung kann auf Wunsch mit einer Eigenschaftsdefinition in einer Objektdeklaration kombiniert werden. In diesem Fall wird die Syntax der Eigenschaftsdefinition zu::

[default] property <propertyType> <propertyName> : <value>

Es folgt ein Beispiel für die Initialisierung von Eigenschaftswerten:

import QtQuick

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}
Imperative Wertzuweisung

Bei einer imperativen Wertzuweisung wird einer Eigenschaft ein Eigenschaftswert (entweder ein statischer Wert oder ein Bindungsausdruck) aus imperativem JavaScript-Code zugewiesen. Die Syntax einer imperativen Wertzuweisung ist nur der JavaScript-Zuweisungsoperator, wie unten gezeigt:

[<objectId>.]<propertyName> = value

Es folgt ein Beispiel für eine imperative Wertzuweisung:

import QtQuick

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

Statische Werte und Werte mit Bindungsausdruck

Wie bereits erwähnt, gibt es zwei Arten von Werten, die einer Eigenschaft zugewiesen werden können: statische Werte und Werte mit Bindungsausdruck. Letztere werden auch als Eigenschaftsbindungen bezeichnet.

ArtSemantik
Statischer WertEin konstanter Wert, der nicht von anderen Eigenschaften abhängt.
BindungsausdruckEin JavaScript-Ausdruck, der die Beziehung einer Eigenschaft zu anderen Eigenschaften beschreibt. Die Variablen in diesem Ausdruck werden als Abhängigkeiten der Eigenschaft bezeichnet.

Die QML-Engine erzwingt die Beziehung zwischen einer Eigenschaft und ihren Abhängigkeiten. Wenn sich der Wert einer der Abhängigkeiten ändert, wertet die QML-Engine den Bindungsausdruck automatisch neu aus und ordnet das neue Ergebnis der Eigenschaft zu.

Das folgende Beispiel zeigt, wie beide Arten von Werten den Eigenschaften zugewiesen werden:

import QtQuick

Rectangle {
    // both of these are static value assignments on initialization
    width: 400
    height: 200

    Rectangle {
        // both of these are binding expression value assignments on initialization
        width: parent.width / 2
        height: parent.height
    }
}

Hinweis: Um einen Bindungsausdruck zwingend zuzuweisen, muss der Bindungsausdruck in einer Funktion enthalten sein, die an Qt.binding() übergeben wird, und dann muss der von Qt.binding() zurückgegebene Wert der Eigenschaft zugewiesen werden. Im Gegensatz dazu darf Qt.binding() nicht verwendet werden, wenn ein Bindungsausdruck bei der Initialisierung zugewiesen wird. Siehe Property Binding für weitere Informationen.

Typsicherheit

Eigenschaften sind typsicher. Einer Eigenschaft kann nur ein Wert zugewiesen werden, der dem Typ der Eigenschaft entspricht.

Wenn eine Eigenschaft beispielsweise ein Real ist und Sie versuchen, ihr einen String zuzuweisen, erhalten Sie einen Fehler:

property int volume: "four"  // generates an error; the property's object will not be loaded

Wenn einer Eigenschaft während der Laufzeit ein Wert des falschen Typs zugewiesen wird, wird der neue Wert nicht zugewiesen und es wird ein Fehler erzeugt.

Einige Eigenschaftstypen haben keine natürliche Wertdarstellung, und für diese Eigenschaftstypen führt die QML-Engine automatisch eine Konvertierung von Strings in typisierte Werte durch. So können Sie beispielsweise einer Farbeigenschaft die Zeichenkette "red" zuweisen, obwohl Eigenschaften vom Typ color Farben und keine Zeichenketten speichern, ohne dass ein Fehler gemeldet wird.

Eine Liste der standardmäßig unterstützten Eigenschaftstypen finden Sie unter QML-Wertetypen. Darüber hinaus kann jeder verfügbare QML-Objekttyp auch als Eigenschaftstyp verwendet werden.

Spezielle Eigenschaftstypen

Objektlisten-Eigenschaftsattribute

Einer Eigenschaft des Typs list kann eine Liste von QML-Objekttypwerten zugewiesen werden. Die Syntax für die Definition eines Objektlistenwertes ist eine durch Komma getrennte Liste, die von eckigen Klammern umgeben ist:

[ <item 1>, <item 2>, ... ]

Der Typ Item verfügt beispielsweise über eine Eigenschaft states, die zur Aufnahme einer Liste von Objekten des Typs State verwendet wird. Der folgende Code initialisiert den Wert dieser Eigenschaft mit einer Liste von drei State Objekten:

import QtQuick

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

Wenn die Liste nur ein einziges Element enthält, können die eckigen Klammern weggelassen werden:

import QtQuick

Item {
    states: State { name: "running" }
}

Eine Eigenschaft vom Typ list kann in einer Objektdeklaration mit der folgenden Syntax angegeben werden:

[default] property list<<ObjectType>> propertyName

und, wie andere Eigenschaftsdeklarationen, kann eine Eigenschaftsinitialisierung mit der Eigenschaftsdeklaration mit der folgenden Syntax kombiniert werden:

[default] property list<<ObjectType>> propertyName: <value>

Es folgt ein Beispiel für die Deklaration einer Listeneigenschaft:

import QtQuick

Rectangle {
    // declaration without initialization
    property list<Rectangle> siblingRects

    // declaration with initialization
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

Wenn Sie eine Eigenschaft deklarieren möchten, um eine Liste von Werten zu speichern, die nicht unbedingt Werte vom Typ QML-Objekt sind, sollten Sie stattdessen eine var Eigenschaft deklarieren.

Gruppierte Eigenschaften

In manchen Fällen enthalten Eigenschaften eine logische Gruppe von Untereigenschaftsattributen. Diese Untereigenschaftsattribute können entweder mit der Punktnotation oder der Gruppennotation zugewiesen werden.

Zum Beispiel hat der Typ Text eine Gruppeneigenschaft font. Im Folgenden initialisiert das erste Objekt Text seine font Werte mit der Punktnotation, während das zweite Objekt die Gruppennotation verwendet:

Text {
    //dot notation
    font.pixelSize: 12
    font.b: true
}

Text {
    //group notation
    font { pixelSize: 12; b: true }
}

Gruppeneigenschaftstypen sind Typen, die Untereigenschaften haben. Wenn ein gruppierter Eigenschaftstyp ein Objekttyp ist (im Gegensatz zu einem Wertetyp), muss die Eigenschaft, die ihn enthält, schreibgeschützt sein. Dies soll verhindern, dass Sie das Objekt, zu dem die Untereigenschaften gehören, ersetzen können.

Eigenschaftsalias

Eigenschafts-Aliase sind Eigenschaften, die einen Verweis auf eine andere Eigenschaft enthalten. Im Gegensatz zu einer gewöhnlichen Eigenschaftsdefinition, die einen neuen, eindeutigen Speicherplatz für die Eigenschaft zuweist, verbindet ein Eigenschaftsalias die neu deklarierte Eigenschaft (die so genannte Aliaseigenschaft) als direkten Verweis auf eine bestehende Eigenschaft (die Aliaseigenschaft).

Eine Eigenschaftsalias-Deklaration sieht aus wie eine gewöhnliche Eigenschaftsdefinition, außer dass sie das Schlüsselwort alias anstelle eines Eigenschaftstyps erfordert und die rechte Seite der Eigenschaftsdeklaration eine gültige Alias-Referenz sein muss:

[default] property alias <name>: <alias reference>

Im Gegensatz zu einer gewöhnlichen Eigenschaft hat ein Alias die folgenden Einschränkungen:

  • Er kann nur auf ein Objekt oder die Eigenschaft eines Objekts verweisen, das in den Geltungsbereich des Typs fällt, innerhalb dessen der Alias deklariert ist.
  • Er kann keine willkürlichen JavaScript-Ausdrücke enthalten.
  • Er kann nicht auf Objekte verweisen, die außerhalb des Geltungsbereichs seines Typs deklariert sind.
  • Der Verweis auf den Alias ist nicht optional, anders als der optionale Standardwert für eine gewöhnliche Eigenschaft; der Verweis auf den Alias muss bei der ersten Deklaration des Alias angegeben werden.
  • Er kann nicht auf angehängte Eigenschaften verweisen.
  • Er kann nicht auf Eigenschaften innerhalb einer Hierarchie mit einer Tiefe von 3 oder mehr verweisen. Der folgende Code wird nicht funktionieren:
    property alias color: myItem.myRect.border.color
    
    Item {
        id: myItem
        property Rectangle myRect
    }

    Aliasnamen für Eigenschaften, die bis zu zwei Ebenen tief sind, funktionieren jedoch.

    property alias color: rectangle.border.color
    
    Rectangle {
        id: rectangle
    }

Zum Beispiel ist unten ein Button Typ mit einer buttonText Aliaseigenschaft, die mit dem text Objekt des Text Kindes verbunden ist:

// Button.qml
import QtQuick

Rectangle {
    property alias buttonText: textItem.text

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

Der folgende Code würde ein Button mit einer definierten Textzeichenfolge für das untergeordnete Text Objekt erstellen:

Button { buttonText: "Click Me" }

In diesem Fall wird durch die Änderung von buttonText direkt der Wert von textItem.text geändert; es wird nicht ein anderer Wert geändert, der dann textItem.text aktualisiert. Wäre buttonText kein Alias, würde die Änderung seines Wertes den angezeigten Text überhaupt nicht ändern, da Eigenschaftsbindungen nicht bidirektional sind: Der Wert buttonText hätte sich geändert, wenn textItem.text geändert worden wäre, aber nicht umgekehrt.

Überlegungen zu Eigenschaftsaliasen

Es ist möglich, dass eine Aliasing-Eigenschaft denselben Namen wie eine vorhandene Eigenschaft hat und die vorhandene Eigenschaft dadurch überschrieben wird. Der folgende QML-Typ verfügt beispielsweise über eine Alias-Eigenschaft color, die denselben Namen trägt wie die eingebaute Eigenschaft Rectangle::color:

Rectangle {
    id: coloredrectangle
    property alias color: bluerectangle.color
    color: "red"

    Rectangle {
        id: bluerectangle
        color: "#1234ff"
    }

    Component.onCompleted: {
        console.log (coloredrectangle.color)    //prints "#1234ff"
        setInternalColor()
        console.log (coloredrectangle.color)    //prints "#111111"
        coloredrectangle.color = "#884646"
        console.log (coloredrectangle.color)    //prints #884646
    }

    //internal function that has access to internal properties
    function setInternalColor() {
        color = "#111111"
    }
}

Jedes Objekt, das diesen Typ verwendet und auf seine Eigenschaft color verweist, bezieht sich auf den Alias und nicht auf die normale Eigenschaft Rectangle::color. Intern kann das Rechteck jedoch seine Eigenschaft color korrekt setzen und auf die tatsächlich definierte Eigenschaft statt auf den Alias verweisen.

Eigenschaftsalias und Typen

Eigenschaftsalias können keine expliziten Typangaben haben. Der Typ eines Eigenschaftsalias ist der deklarierte Typ der Eigenschaft oder des Objekts, auf das er verweist. Wenn Sie also einen Alias für ein Objekt erstellen, auf das über id verwiesen wird und dessen zusätzliche Eigenschaften inline deklariert sind, sind die zusätzlichen Eigenschaften nicht über den Alias zugänglich:

// MyItem.qml
Item {
    property alias inner: innerItem

    Item {
        id: innerItem
        property int extraProperty
    }
}

Sie können inner.extraProperty nicht von außerhalb dieser Komponente initialisieren, da inner nur ein Item ist:

// main.qml
MyItem {
    inner.extraProperty: 5 // fails
}

Wenn Sie jedoch das innere Objekt in eine separate Komponente mit einer eigenen .qml-Datei extrahieren, können Sie diese Komponente stattdessen instanziieren und haben alle ihre Eigenschaften über den Alias verfügbar:

// MainItem.qml
Item {
    // Now you can access inner.extraProperty, as inner is now an ExtraItem
    property alias inner: innerItem

    ExtraItem {
        id: innerItem
    }
}

// ExtraItem.qml
Item {
    property int extraProperty
}

Standard-Eigenschaften

Eine Objektdefinition kann eine einzige Standardeigenschaft haben. Eine Standardeigenschaft ist die Eigenschaft, der ein Wert zugewiesen wird, wenn ein Objekt innerhalb der Definition eines anderen Objekts deklariert wird, ohne es als Wert für eine bestimmte Eigenschaft zu deklarieren.

Wenn eine Eigenschaft mit dem optionalen Schlüsselwort default deklariert wird, wird sie als Standardeigenschaft gekennzeichnet. Angenommen, es gibt eine Datei MyLabel.qml mit einer Standardeigenschaft someText:

// MyLabel.qml
import QtQuick

Text {
    default property var someText

    text: `Hello, ${someText.text}`
}

Der Wert someText könnte in einer MyLabel Objektdefinition zugewiesen werden, etwa so:

MyLabel {
    Text { text: "world!" }
}

Dies hat genau die gleiche Wirkung wie das Folgende:

MyLabel {
    someText: Text { text: "world!" }
}

Da jedoch die Eigenschaft someText als Standardeigenschaft markiert wurde, ist es nicht erforderlich, das Objekt Text explizit dieser Eigenschaft zuzuweisen.

Sie werden feststellen, dass untergeordnete Objekte zu jedem Item-basierten Typ hinzugefügt werden können, ohne sie explizit der Eigenschaft children hinzuzufügen. Das liegt daran, dass die Standardeigenschaft von Item die Eigenschaft data ist, und alle Elemente, die dieser Liste für Item hinzugefügt werden, werden automatisch der Liste von children hinzugefügt.

Standardeigenschaften können nützlich sein, um die Kinder eines Elements neu zuzuordnen. Ein Beispiel:

Item {
    default property alias content: inner.children

    Item {
        id: inner
    }
}

Wenn Sie die Standardeigenschaft alias auf inner.children setzen, wird jedes Objekt, das als Kind des äußeren Elements zugewiesen wird, automatisch als Kind des inneren Elements neu zugewiesen.

Warnung: Die Einstellung der Werte der Standardeigenschaft eines Elements kann implizit oder explizit erfolgen. Innerhalb der Definition eines einzelnen Elements dürfen diese beiden Methoden nicht vermischt werden, da dies zu einer undefinierten Anordnung der Elemente in der Liste führt.

Item {
    // Use either implicit or explicit assignement to the default list property but not both!
    Rectangle { width: 40 }            // implicit
    data: [ Rectangle { width: 100 } ] // explicit
}

Erforderliche Eigenschaften

In einer Objektdeklaration kann eine Eigenschaft als erforderlich definiert werden, indem das Schlüsselwort required verwendet wird. Die Syntax lautet

required property <propertyType> <propertyName>

Wie der Name schon sagt, müssen erforderliche Eigenschaften gesetzt werden, wenn eine Instanz des Objekts erstellt wird. Ein Verstoß gegen diese Regel führt dazu, dass QML-Anwendungen nicht gestartet werden, wenn dies statisch erkannt werden kann. Bei dynamisch instanzierten QML-Komponenten (z.B. über Qt.createComponent()) führt ein Verstoß gegen diese Regel zu einer Warnung und einem Null-Rückgabewert.

Es ist möglich, eine existierende Eigenschaft erforderlich zu machen mit

required <propertyName>

Das folgende Beispiel zeigt, wie man eine benutzerdefinierte Rectangle-Komponente erstellt, bei der die Eigenschaft color immer angegeben werden muss.

// ColorRectangle.qml
Rectangle {
    required color
}

Hinweis: Sie können einer erforderlichen Eigenschaft aus QML heraus keinen Anfangswert zuweisen, da dies direkt gegen die beabsichtigte Verwendung von erforderlichen Eigenschaften verstoßen würde.

Erforderliche Eigenschaften spielen eine besondere Rolle in Model-View-Delegate Code: Wenn der Delegat einer Ansicht erforderliche Eigenschaften hat, deren Namen mit den Rollennamen des Modells der Ansicht übereinstimmen, dann werden diese Eigenschaften mit den entsprechenden Werten des Modells initialisiert. Weitere Informationen finden Sie auf der Seite Modelle und Ansichten in Qt Quick.

Siehe QQmlComponent::createWithInitialProperties, QQmlApplicationEngine::setInitialProperties und QQuickView::setInitialProperties für Möglichkeiten, erforderliche Eigenschaften von C++ aus zu initialisieren.

Nur-Lese-Eigenschaften

Eine Objektdeklaration kann eine schreibgeschützte Eigenschaft mit dem Schlüsselwort readonly mit der folgenden Syntax definieren:

readonly property <propertyType> <propertyName> : <value>

Schreibgeschützten Eigenschaften muss bei der Initialisierung ein statischer Wert oder ein Bindungsausdruck zugewiesen werden. Nachdem eine schreibgeschützte Eigenschaft initialisiert wurde, können Sie ihren statischen Wert oder Bindungsausdruck nicht mehr ändern.

Der Code im folgenden Component.onCompleted -Block ist zum Beispiel ungültig:

Item {
    readonly property int someNumber: 10

    Component.onCompleted: someNumber = 20  // TypeError: Cannot assign to read-only property
}

Hinweis: Eine schreibgeschützte Eigenschaft kann nicht gleichzeitig eine Standardeigenschaft sein.

Eigenschaftsmodifikator-Objekte

Eigenschaften können mit Property-Value-Modifier-Objekten verknüpft sein. Die Syntax für die Deklaration einer Instanz eines Eigenschaftsmodifikatortyps in Verbindung mit einer bestimmten Eigenschaft lautet wie folgt:

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

Dies wird gemeinhin als "on"-Syntax bezeichnet.

Es ist wichtig zu beachten, dass die obige Syntax in Wirklichkeit eine Objektdeklaration ist, die ein Objekt instanziiert, das auf eine bereits vorhandene Eigenschaft wirkt.

Bestimmte Typen von Eigenschaftsmodifikatoren können nur auf bestimmte Eigenschaftstypen anwendbar sein, dies wird jedoch von der Sprache nicht erzwungen. So kann beispielsweise der Typ NumberAnimation, der von QtQuick bereitgestellt wird, nur Eigenschaften des numerischen Typs (wie int oder real) beleben. Der Versuch, eine NumberAnimation mit einer nicht-numerischen Eigenschaft zu verwenden, führt nicht zu einem Fehler, aber die nicht-numerische Eigenschaft wird nicht animiert. Das Verhalten eines Eigenschaftsmodifikatortyps in Verbindung mit einem bestimmten Eigenschaftstyp wird durch seine Implementierung definiert.

Signal-Attribute

Ein Signal ist eine Benachrichtigung von einem Objekt, dass ein bestimmtes Ereignis eingetreten ist: zum Beispiel, dass sich eine Eigenschaft geändert hat, dass eine Animation gestartet oder gestoppt wurde oder dass ein Bild heruntergeladen wurde. Der Typ MouseArea verfügt zum Beispiel über ein Signal clicked, das ausgegeben wird, wenn der Benutzer in den Mausbereich klickt.

Ein Objekt kann über einen Signalhandler benachrichtigt werden, wenn ein bestimmtes Signal ausgegeben wird. Ein Signalhandler wird mit der Syntax on<Signal> deklariert, wobei <Signal> der Name des Signals ist, wobei der erste Buchstabe groß geschrieben wird. Der Signal-Handler muss innerhalb der Definition des Objekts deklariert werden, das das Signal aussendet, und der Handler sollte den JavaScript-Codeblock enthalten, der ausgeführt wird, wenn der Signal-Handler aufgerufen wird.

Der folgende onClicked-Signal-Handler wird beispielsweise in der Definition des Objekts MouseArea deklariert und aufgerufen, wenn MouseArea angeklickt wird, wodurch eine Konsolenmeldung ausgegeben wird:

import QtQuick

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

Definieren von Signalattributen

Ein Signal kann für einen Typ in C++ definiert werden, indem eine Q_SIGNAL einer Klasse registriert wird, die dann im QML-Typsystem registriert wird. Alternativ dazu kann ein benutzerdefiniertes Signal für einen Objekttyp in einer Objektdeklaration in einem QML-Dokument mit der folgenden Syntax definiert werden:

signal <signalName>[([<parameterName>: <parameterType>[, ...]])]

Der Versuch, zwei Signale oder Methoden mit demselben Namen in demselben Typblock zu deklarieren, ist ein Fehler. Ein neues Signal kann jedoch den Namen eines bestehenden Signals des Typs wiederverwenden. (Dies ist mit Vorsicht zu genießen, da das vorhandene Signal versteckt und unzugänglich werden kann).

Hier sind drei Beispiele für Signaldeklarationen:

import QtQuick

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(action: string, actionResult: int)
}

Sie können Signalparameter auch in einer eigenschaftsähnlichen Syntax angeben:

signal actionCanceled(string action)

Um mit Methodendeklarationen konsistent zu sein, sollten Sie die Typdeklarationen mit Doppelpunkten vorziehen.

Wenn das Signal keine Parameter hat, sind die Klammern "()" optional. Wenn Parameter verwendet werden, müssen die Parametertypen deklariert werden, wie bei den Argumenten string und int für das obige Signal actionPerformed. Die zulässigen Parametertypen sind die gleichen wie die, die unter Definieren von Eigenschaftsattributen auf dieser Seite aufgeführt sind.

Um ein Signal auszusenden, rufen Sie es als Methode auf. Alle relevanten Signalhandler werden aufgerufen, wenn das Signal ausgesendet wird, und die Handler können die definierten Signalargumentnamen verwenden, um auf die jeweiligen Argumente zuzugreifen.

Signale für Eigenschaftsänderungen

QML-Typen bieten auch eingebaute Eigenschaftsänderungssignale, die immer dann ausgegeben werden, wenn sich ein Eigenschaftswert ändert, wie zuvor im Abschnitt über Eigenschaftsattribute beschrieben. Weitere Informationen darüber, warum diese Signale nützlich sind und wie man sie verwendet, finden Sie im nächsten Abschnitt über Signalhandler für Eigenschaftsänderungen.

Signalhandler-Attribute

Signalhandler sind eine spezielle Art von Methodenattributen, bei denen die Methodenimplementierung von der QML-Engine aufgerufen wird, sobald das zugehörige Signal ausgegeben wird. Das Hinzufügen eines Signals zu einer Objektdefinition in QML fügt automatisch einen zugehörigen Signalhandler zur Objektdefinition hinzu, der standardmäßig eine leere Implementierung hat. Clients können eine Implementierung bereitstellen, um Programmlogik zu implementieren.

Betrachten wir den folgenden Typ SquareButton, dessen Definition in der Datei SquareButton.qml wie unten gezeigt bereitgestellt wird, mit den Signalen activated und deactivated:

// SquareButton.qml
Rectangle {
    id: root

    signal activated(xPosition: real, yPosition: real)
    signal deactivated

    property int side: 100
    width: side; height: side

    MouseArea {
        anchors.fill: parent
        onReleased: root.deactivated()
        onPressed: mouse => root.activated(mouse.x, mouse.y)
    }
}

Diese Signale können von beliebigen SquareButton Objekten in einer anderen QML-Datei im selben Verzeichnis empfangen werden, in der Implementierungen für die Signal-Handler vom Client bereitgestellt werden:

// myapplication.qml
SquareButton {
    onDeactivated: console.log("Deactivated!")
    onActivated: (xPosition, yPosition) => {
        console.log(`Activated at ${xPosition}, ${yPosition}`)
    }
}

Signalhandler müssen ihre Parametertypen nicht deklarieren, da das Signal sie bereits angibt. Die oben gezeigte Syntax für Pfeilfunktionen unterstützt keine Typ-Annotationen.

Weitere Details zur Verwendung von Signalen finden Sie im Signal- und Handler-Ereignissystem.

Handler für Eigenschaftsänderungssignale

Signalhandler für Eigenschaftsänderungssignale haben die Syntaxform on<Eigenschaft>Changed, wobei <Eigenschaft> der Name der Eigenschaft ist, wobei der erste Buchstabe groß geschrieben wird. Obwohl die Dokumentation des Typs TextInput zum Beispiel kein textChanged -Signal dokumentiert, ist dieses Signal implizit verfügbar, da TextInput eine text -Eigenschaft hat. Daher ist es möglich, einen onTextChanged -Signal-Handler zu schreiben, der aufgerufen wird, wenn sich diese Eigenschaft ändert:

import QtQuick

TextInput {
    text: "Change this!"

    onTextChanged: console.log(`Text has changed to: ${text}`)
}

Methoden-Attribute

Eine Methode eines Objekttyps ist eine Funktion, die aufgerufen werden kann, um eine Verarbeitung durchzuführen oder weitere Ereignisse auszulösen. Eine Methode kann mit einem Signal verknüpft werden, so dass sie automatisch aufgerufen wird, wenn das Signal ausgegeben wird. Siehe Signal und Handler Event System für weitere Details.

Definieren von Methodenattributen

Eine Methode kann für einen Typ in C++ definiert werden, indem eine Funktion einer Klasse markiert wird, die dann im QML-Typsystem mit Q_INVOKABLE oder als Q_SLOT der Klasse registriert wird. Alternativ kann eine benutzerdefinierte Methode zu einer Objektdeklaration in einem QML-Dokument mit der folgenden Syntax hinzugefügt werden:

function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }

Methoden können zu einem QML-Typ hinzugefügt werden, um eigenständige, wiederverwendbare Blöcke von JavaScript-Code zu definieren. Diese Methoden können entweder intern oder von externen Objekten aufgerufen werden.

Im Gegensatz zu Signalen müssen die Typen der Methodenparameter nicht deklariert werden, da sie standardmäßig dem Typ var entsprechen. Sie sollten sie jedoch deklarieren, um qmlcachegen zu helfen, performanteren Code zu generieren und die Wartbarkeit zu verbessern.

Der Versuch, zwei Methoden oder Signale mit demselben Namen im selben Typblock zu deklarieren, ist ein Fehler. Allerdings kann eine neue Methode den Namen einer bestehenden Methode des Typs wiederverwenden. (Dies sollte mit Vorsicht geschehen, da die vorhandene Methode möglicherweise versteckt wird und nicht mehr zugänglich ist).

Nachfolgend finden Sie eine Rectangle mit einer Methode calculateHeight(), die aufgerufen wird, wenn der Wert height zugewiesen wird:

import QtQuick
Rectangle {
    id: rect

    function calculateHeight(): real {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

Wenn die Methode Parameter hat, sind diese über den Namen innerhalb der Methode zugänglich. Wenn MouseArea angeklickt wird, wird die Methode moveTo() aufgerufen, die sich dann auf die empfangenen Parameter newX und newY beziehen kann, um den Text neu zu positionieren:

import QtQuick

Item {
    width: 200; height: 200

    MouseArea {
        anchors.fill: parent
        onClicked: mouse => label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label

        function moveTo(newX: real, newY: real) {
            label.x = newX;
            label.y = newY;
        }

        text: "Move me!"
    }
}

Angehängte Eigenschaften und angehängte Signalhandler

Angehängte Eigenschaften und angehängte Signalhandler sind Mechanismen, die es ermöglichen, Objekte mit zusätzlichen Eigenschaften oder Signalhandlern zu versehen, die sonst für das Objekt nicht verfügbar sind. Insbesondere ermöglichen sie es Objekten, auf Eigenschaften oder Signale zuzugreifen, die speziell für das einzelne Objekt relevant sind.

Eine QML-Typ-Implementierung kann sich dafür entscheiden, einen anhängenden Typ in C++ mit bestimmten Eigenschaften und Signalen zu erstellen. Instanzen dieses Typs können dann erstellt und zur Laufzeit an bestimmte Objekte angehängt werden, so dass diese Objekte auf die Eigenschaften und Signale des anhängenden Typs zugreifen können. Der Zugriff erfolgt durch Voranstellen des Namens des anhängenden Typs vor die Eigenschaften und die entsprechenden Signalhandler.

Verweise auf angehängte Eigenschaften und Handler haben die folgende Syntaxform:

<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>

Der Typ ListView hat beispielsweise eine angehängte Eigenschaft ListView.isCurrentItem, die jedem Delegatenobjekt in einer ListView zur Verfügung steht. Diese kann von jedem einzelnen Delegatenobjekt verwendet werden, um festzustellen, ob es das aktuell ausgewählte Element in der Ansicht ist:

import QtQuick

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

In diesem Fall ist der Name des anhängenden Typs ListView und die betreffende Eigenschaft isCurrentItem, daher wird die angehängte Eigenschaft als ListView.isCurrentItem bezeichnet.

Auf einen angehängten Signalhandler wird auf die gleiche Weise Bezug genommen. Der angehängte Signalhandler Component.onCompleted wird zum Beispiel häufig verwendet, um JavaScript-Code auszuführen, wenn der Erstellungsprozess einer Komponente abgeschlossen ist. Im folgenden Beispiel wird nach der vollständigen Erstellung von ListModel automatisch der Signalhandler Component.onCompleted aufgerufen, um das Modell aufzufüllen:

import QtQuick

ListView {
    width: 240; height: 320
    model: ListModel {
        id: listModel
        Component.onCompleted: {
            for (let i = 0; i < 10; i++) {
                append({ Name: `Item ${i}` })
            }
        }
    }
    delegate: Text { text: index }
}

Da der Name des angehängten Typs Component ist und dieser Typ ein completed Signal hat, wird der angehängte Signal-Handler als Component.onCompleted bezeichnet.

Ein Hinweis zum Zugriff auf angehängte Eigenschaften und Signalhandler

Ein häufiger Fehler ist die Annahme, dass angehängte Eigenschaften und Signalhandler direkt von den Kindern des Objekts, an das diese Attribute angehängt wurden, zugänglich sind. Dies ist jedoch nicht der Fall. Die Instanz des anhängenden Typs ist nur an bestimmte Objekte angehängt, nicht an das Objekt und alle seine Unterobjekte.

Im Folgenden sehen Sie eine modifizierte Version des früheren Beispiels mit angehängten Eigenschaften. Diesmal ist der Delegat ein Item und die farbige Rectangle ist ein untergeordnetes Objekt dieses Elements:

import QtQuick

ListView {
    width: 240; height: 320
    model: 3
    delegate: Item {
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: ListView.isCurrentItem ? "red" : "yellow" // WRONG! This won't work.
        }
    }
}

Dies funktioniert nicht wie erwartet, da ListView.isCurrentItem nur an das Stammdelegatobjekt angehängt ist, nicht aber an seine Kinder. Da Rectangle ein Kind des Delegaten ist und nicht der Delegat selbst, kann es nicht auf die isCurrentItem angehängte Eigenschaft als ListView.isCurrentItem zugreifen. Stattdessen sollte das Rechteck auf isCurrentItem über den Stammdelegierten zugreifen:

ListView {
    delegate: Item {
        id: delegateItem
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: delegateItem.ListView.isCurrentItem ? "red" : "yellow" // correct
        }
    }
}

Jetzt verweist delegateItem.ListView.isCurrentItem korrekt auf die isCurrentItem angehängte Eigenschaft des Delegaten.

Aufzählung Attribute

Aufzählungen bieten einen festen Satz von benannten Auswahlmöglichkeiten. Sie können in QML mit dem Schlüsselwort enum deklariert werden:

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }
}

Wie oben gezeigt, müssen Aufzählungstypen (z. B. TextType) und Werte (z. B. Normal) mit einem Großbuchstaben beginnen.

Auf Werte wird über <Type>.<EnumerationType>.<Value> oder <Type>.<Value> verwiesen.

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }

    property int textType: MyText.TextType.Normal

    font.bold: textType === MyText.TextType.Heading
    font.pixelSize: textType === MyText.TextType.Heading ? 24 : 12
}

Weitere Informationen über die Verwendung von Aufzählungen in QML finden Sie in der Dokumentation QML Value Types enumeration.

Die Möglichkeit, Aufzählungen in QML zu deklarieren, wurde in Qt 5.10 eingeführt.

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