Не откладывая в долгий ящик, продолжим начатое, то есть рассмотрим 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, который самостоятельно разруливает данные нюансы.
На этом на сегодня завершаем, накидайте вариантов, что наглядно осуществить в ближайшей статье.



