Не откладывая в долгий ящик, продолжим начатое, то есть рассмотрим QML тип AnchorChanges. Вот только это лучше сделать в совокупности с разбором State, так и поступим...
Итак, любой элемент в QML после создания находится в некотором дефолтном состоянии (состоянии по умолчанию). Данному состоянию соответствуют определенные значения свойств и наборы параметров. QML же, в свою очередь, заботливо дает нам механизм для добавления альтернативных возможных состояний объекта, для которых мы можем установить какие-либо другие наборы свойств, либо произвести вызов некого скрипта. Осуществляется все при помощи упомянутого типа State
. По традиции - акцент на практических примерах, которые реально дают понимание о том, что и как функционирует:
import QtQuick 2.15 import QtQuick.Window 2.15 Window { id: mainWindow width: 640 height: 480 visible: true title: qsTr("QML States Review") color: "#303030" Rectangle { id: mainRectangle color: "orange" width: 200 height: 200 anchors.centerIn: parent states: [ State { name: "clickedOnce" PropertyChanges {target: mainRectangle; color: "mediumseagreen"} }, State { name: "clickedTwice" PropertyChanges {target: mainRectangle; color: "lightsteelblue"} } ] MouseArea { anchors.fill: parent onClicked: { switch (mainRectangle.state) { case "": mainRectangle.state = "clickedOnce"; break; case "clickedOnce": mainRectangle.state = "clickedTwice"; break; case "clickedTwice": mainRectangle.state = ""; break; default: mainRectangle.state = ""; break; } } } } }
Поэтапно мы сделали следующее... Добавили Rectangle
, разместив его по центру окна и задав его цвет по умолчанию - color: "orange"
.
К этому же компоненту добавляем возможные состояния. Это делается при помощи свойства states
, которое представляет из себя набор элементов типа State
. В данном случае у нас два элемента, что означает два возможных состояния (помимо дефолтного). И кроме названия состояний закидываем еще PropertyChanges
. Данный тип, в свою очередь, определяет изменение того или иного свойства, указанного в качестве target
объекта. Соответственно, здесь мы меняем цвет у mainRectangle
, чтобы наглядно оценить переход между состояниями.
Ну и непосредственно переход - сделаем так, чтобы состояния менялись по клику мышью на прямоугольник. Один клик - состояние "clickedOnce", еще один клик - "clickedTwice", следующий клик переводит в состояние по умолчанию. Это осуществляется в виде простейшего конечного автомата в MouseArea
. Запускаем, проверяем:
Думаю, идея тут абсолютно ясна, так что перейдем ко второй части - использованию AnchorChanges
. По большому счету, AnchorChanges
по логике использования похож на PropertyChanges
, только изменению подвергаются не свойства, а anchors
элемента.
И, конечно, пример:
import QtQuick 2.15 import QtQuick.Window 2.15 Window { id: mainWindow width: 640 height: 480 visible: true title: qsTr("QML States Review") color: "#303030" Rectangle { id: mainRectangle color: "orange" width: 200 height: 200 anchors.top: parent.top anchors.left: parent.left states: [ State { name: "clickedOnce" PropertyChanges {target: mainRectangle; color: "mediumseagreen"} AnchorChanges {target: mainRectangle; anchors.right: parent.right; anchors.left: undefined} }, State { name: "clickedTwice" PropertyChanges {target: mainRectangle; color: "lightsteelblue"} AnchorChanges {target: mainRectangle; anchors.bottom: parent.bottom; anchors.top: undefined} } ] MouseArea { anchors.fill: parent onClicked: { switch (mainRectangle.state) { case "": mainRectangle.state = "clickedOnce"; break; case "clickedOnce": mainRectangle.state = "clickedTwice"; break; case "clickedTwice": mainRectangle.state = ""; break; default: mainRectangle.state = ""; break; } } } } }
Изменения заключается лишь в добавлении AnchorChanges
к состояниям элемента. Для "clickedOnce":
AnchorChanges {target: mainRectangle; anchors.right: parent.right; anchors.left: undefined}
Изменения надо указывать относительно дефолтного состояния. Здесь по умолчанию Rectangle
в левом верхнем углу. Мы изменяем anchors.right
и anchors.left
, в результате чего он оказывается в правом верхнем углу. Для "clickedTwice":
AnchorChanges {target: mainRectangle; anchors.bottom: parent.bottom; anchors.top: undefined}
И опять же - было "левый верхний", меняем anchors.bottom
/ anchors.top
- получаем левый же, но нижний угол 👌
Может возникнуть вполне резонный вопрос, почему не поменять просто напрямую, допустим:
function changeAnchors() { anchors.right = parent.right; anchors.left = undefined; }
И здесь вступает в силу очередность выполнения инструкций. В данном случае сначала(!) будет изменен anchors.right
(при этом anchors.left
сохранит исходное значение), что приведет к тому, что элемент растянется на всю ширину. Соответственно, последующее изменение anchors.left = undefined
уже ситуации не исправит и вообще ничего не изменит. Этой проблемы помог бы избежать такой вариант:
function changeAnchors() { anchors.left = undefined; anchors.right = parent.right; }
Но для того, чтобы в каждом возможном случае не продумывать всю очередность и потенциальные трудности, лучше использовать изначально AnchorChanges
, который самостоятельно разруливает данные нюансы.
На этом на сегодня завершаем, накидайте вариантов, что наглядно осуществить в ближайшей статье.