Zusätzlich zum traditionelleren Grid, Row, Column bietet Qt Quick auch Funktionen für Ebenenelemente, die das Konzept von Ankern ( Anchors ) verwenden. Jedes Element kann als ein Satz von 7 unsichtbaren "Ankerlinien" angesehen werden:
- left;
- horizontalCenter;
- right;
- top;
- verticalCenter;
- baseline;
- bottom.
Grundlinie (in dieser Abbildung) entspricht einer imaginären Linie, auf der Text platziert wird. Bei Elementen ohne Text entspricht dies der Zeile top.
Mit dem Ankersystem Qt Quick können Sie Beziehungen zwischen den Ankerlinien verschiedener Elemente definieren. Sie können zum Beispiel schreiben:
Rectangle { id: rect1; ... } Rectangle { id: rect2; anchors.left: rect1.right; ... }
In diesem Fall wird die linke Seite von rect2 mit der rechten Seite von rect1 verbunden und sieht so aus:
Sie können mehrere Anker angeben. Zum Beispiel:
Rectangle { id: rect1; ... } Rectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }
Indem Sie mehrere horizontale oder vertikale Anker angeben, können Sie die Größe eines Elements steuern. Im Bild unten ist rect2 auf der rechten Seite mit rect1 und auf der linken Seite mit rect3 verankert. Wenn eines der blauen Rechtecke verschoben wird, wird rect2 entsprechend erweitert oder verkleinert:
Es gibt auch einige praktische Ankerfunktionen wie anchors.fill , die left, right, top und bottom Anker auf das Zielelement setzen. anchors.centerIn entspricht der gleichzeitigen Verwendung von verticalCenter und horizontalCenter relativ zum Zielelement. Das heißt, setzt ein anderes Element in die Mitte des Zielelements.
Ankerränder (Felder) und Offsets (Offsets)
Mit dem Ankersystem können Sie auch Ränder und Versätze für bestimmte Elementanker festlegen. Ränder geben den Leerraum an, der sich zwischen der Ankerlinie und dem Element befinden sollte, während der Versatz es ermöglicht, die Positionierung über die Mitte der Ankerlinien zu steuern. Ein Element kann Ränder für jeden Anker einzeln über leftMargin, rightMargin, topMargin, bottomMargin angeben oder mithilfe von anchors.margins einen Randwert für alle vier Seiten angeben. Anker-Offsets werden mit horizontalCenterOffset, verticalCenterOffset und baselineOffset angegeben.
Das folgende Beispiel gibt einen linken Rand an:
Rectangle { id: rect1; ... } Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }
In diesem Fall ist der Rand 5 Pixel links von rect2:
Hinweis: Ankerfelder werden nur für Anker verwendet, sie werden nicht für Elemente verwendet. Das heißt, wenn für eine bestimmte Seite ein Rand angegeben ist, das Element jedoch nicht an der Seite eines Elements verankert ist, wird der Rand nicht angewendet.
Anker ändern
Qt Quick bietet den Typ AnchorChanges zum Angeben des Status eines Ankers.
State { name: "anchorRight" AnchorChanges { target: rect2 anchors.right: parent.right anchors.left: undefined //remove the left anchor } }
AnchorChanges können mit dem Typ AnchorAnimation. animiert werden
Transition { AnchorAnimation {} //animates any AnchorChanges in the corresponding state change }
Anker können auch direkt per JavaScript geändert werden. Diese Änderungen müssen jedoch mit Vorsicht vorgenommen werden, da sie zu unvorhersehbaren Ergebnissen führen können. Folgendes Beispiel verdeutlicht das Problem:
//bad code Rectangle { width: 50 anchors.left: parent.left function reanchorToRight() { anchors.right = parent.right anchors.left = undefined } }
Im Beispiel wird der rechte Anker am Anfang gesetzt. Sobald der linke und der rechte Anker gesetzt sind, wird das Element horizontal über sein übergeordnetes Element gestreckt. Wenn der linke Anker entfernt wird, erhält das Element eine neue Breiteneinstellung. Infolgedessen ändern sich die Breitenparameter des Objekts, während wir die angegebene Breite des Objekts beibehalten müssen. Dazu müssen Sie zuerst den linken Anker entfernen und dann den rechten Anker installieren.
Rectangle { width: 50 anchors.left: parent.left function reanchorToRight() { anchors.left = undefined anchors.right = parent.right } }
Da Ankerwerte nicht definiert sind, ist es nicht empfehlenswert, Anker über bedingte Anker zu ändern, da dies zu dem oben beschriebenen Problem führen kann. Im folgenden Beispiel dehnt sich das Rechteck schließlich auf die volle Breite seines übergeordneten Elements aus, da beide Anker gleichzeitig während der Aktualisierung der Anker gesetzt werden.
//bad code Rectangle { width: 50; height: 50 anchors.left: state == "right" ? undefined : parent.left; anchors.right: state == "right" ? parent.right : undefined; }
Dieser Code sollte über AnchorChenges umgeschrieben werden, wodurch Ankerbindungen automatisch verarbeitet werden.
Beschränkungen
Um die Leistung zu verbessern, können Sie nur direkt mit dem übergeordneten Element oder mit gleichgeordneten Elementen verankern, d. h. mit Elementen, die sich im selben übergeordneten Element wie dieses Element befinden. Der folgende Code ist beispielsweise nicht korrekt:
//bad code Item { id: group1 Rectangle { id: rect1; ... } } Item { id: group2 Rectangle { id: rect2; anchors.left: rect1.right; ... } // invalid anchor! }
Außerdem können ankerbasierte Ebenen nicht mit absoluter Positionierung gemischt werden. Wenn einem Element seine Position gegeben wird und zusätzlich acnhors.left gesetzt wird, oder zusätzlich zum linken und rechten Anker die Breite des Elements angegeben wird, dann ist das Ergebnis undefiniert, da nicht bekannt ist, ob anchors oder absolute Positionierung verwendet werden. Dasselbe gilt für die Elementhöhe und die Verwendung von top und bottom Ankern oder das Setzen von acnhors.fill zum Festlegen von Höhe oder Breite. Dasselbe gilt für das Festlegen von Objekten wie Row und Grid , die x - und y -Eigenschaften für Elemente festlegen können. Wenn Sie die Ankerposition auf absolut ändern möchten, muss der Ankerwert gelöscht werden.