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:
(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.
Art | Semantik |
---|---|
Statischer Wert | Ein konstanter Wert, der nicht von anderen Eigenschaften abhängt. |
Bindungsausdruck | Ein 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:
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.