Крайне удобным способом позиционирования различных QML компонентов является использование так называемых Anchors. Что в переводе ближе всего к "якорям", но мне русификация такого типа обычно не слишком нравится. Поэтому я, хоть специально на этом не концентрируюсь и внимания не обращаю, тем не менее в тексте на автомате скорее всего буду писать "anchors". Минутка филологии завершена, давайте рассмотрим несколько основных практических примеров использования данного механизма.
QML Anchors. Краткие теоретические сведения.
Итак, идея заключается в том, что у каждого элемента есть некий набор свойств, благодаря которым можно полностью управлять его расположением относительно других элементов. На примере абстрактного элемента:

Перечень данных свойств включает в себя 7 пунктов:
- top
- bottom
- left
- right
- horizontalCenter
- verticalCenter
- baseline
По сути мы получаем 7 линий, задавая положение которых, осуществляем перемещение компонента, к которому эти линии относятся 👍 Все линии изображены на схеме, поэтому не останавливаемся, рассмотрим конкретные варианты использования. Как вы заметили, baseline не изображена, о ней речь пойдет чуть ниже.
QML Anchors. Примеры позиционирования.
Начинаем с пустого Qt Quick приложения, объектом изменений будет исключительно файл main.qml:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
}
Начнем вопреки логике с не упомянутого ранее свойства - anchors.fill. Его установка эквивалентна изменению top, bottom, left и right одновременно:
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
Rectangle {
color: "#008080"
anchors.fill: parent
}
}
В результате Rectangle займет все пространство окна:

Аналогичного эффекта можно было добиться так:
anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.bottom: parent.bottom
Собственно, экономия и удобство anchors.fill налицо. Теперь допустим нам нужно добиться такого эффекта для двух прямоугольников:

Высота верхнего прямоугольника пусть будет фиксированной, а нижнего - определяться тем свободным пространство окна, которое ему останется. Anchors получаем следующие:

Ровно так и делаем и получаем в точности такой результат, как требовалось:
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
Rectangle {
id: blueRectangle
color: "#008080"
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 320
}
Rectangle {
id: greenRectangle
color: "#3CB371"
anchors.top: blueRectangle.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
}
}
При этом для верхнего объекта мы не задаем anchors.bottom, поскольку его высота задана явно. А если мы помимо height задали еще и anchors.bottom, то возникло бы противоречие - высота задана как относительно, при помощи anchors.top и anchors.bottom, так и абсолютно через height. Такие коллапсы недопустимы. Это же касается и задания ширины, да и любых аспектов абсолютного позиционирования, которые могут конфликтовать с позиционированием при помощи anchors.
С "основными" линиями - top, bottom, left, right - все понятно, рассмотрим оставшиеся 3 варианта. Снова оставляем один Rectangle, зададим ему фиксированные размеры и поставим задачу расположить его четко по центру окна:
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
Rectangle {
id: blueRectangle
color: "#008080"
width: 320
height: 240
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Суть здесь также проста. Anchors - это конкретные линии конкретного объекта. Поэтому мы имеем в наличию линию, соответствующую horizontalCenter, как у blueRectangle, так и у его родителя, которым в данном случае является основное окно приложения. И затем мы просто задаем положение этой линии у прямоугольника, чтобы она совпадала с аналогичной у окна:

Как и в случае с anchors.fill есть дополнительный вариант, упрощающий жизнь, и в данном случае это - anchors.centerIn. Аналогичного позиционирования в данном примере мы могли достигнуть и так:
anchors.centerIn: parent
Пройдемся по свойству baseline, которое часто незаслуженно упоминается лишь поверхностно парой фраз. Данная линия относится к воображаемой линии, на которой находится текст. У рассмотренных прямоугольников текст отсутствует - для них baseline совпадает с top. Возьмем прямоугольник и кнопку с текстом и посмотрим на разницу:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
Rectangle {
id: blueRectangle
color: "#008080"
height: 240
anchors.left: parent.left
anchors.right: myButton.left
anchors.baseline: parent.verticalCenter
}
Button {
id: myButton
text: qsTr("My Button")
anchors.right: parent.right
anchors.baseline: parent.verticalCenter
}
}
Да, на всякий напоминаю, для Button добавляем:
import QtQuick.Controls 2.15
Результат закономерен с учетом вышеописанного:

QML Anchors. Margins, offsets.
При использовании данной концепции позиционирования редко обходится без задания полей - margins:

То есть margins задает размер пустого пространства между линиями top, bottom, left, right и непосредственно самим элементом. Реализуется свойствами:
- anchors.topMargin
- anchors.bottomMargin
- anchors.leftMargin
- anchors.righrMargin
- и также есть обобщающее свойство anchors.margins, задающее все четыре предыдущих одновременно
Offsets же задают смещения трех неохваченных линий, а именно - horizontalCenter, verticalCenter, baseline. Рассмотрим конкретный пример для случая с двумя прямоугольниками: добавляем поля сверху и слева - для верхнего, снизу и справа - для нижнего:
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
Rectangle {
id: blueRectangle
color: "#008080"
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 30
anchors.topMargin: 30
height: 320
}
Rectangle {
id: greenRectangle
color: "#3CB371"
anchors.top: blueRectangle.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 15
anchors.bottomMargin: 15
}
}

Задав все поля одновременно, добились бы такого эффекта:
Window {
width: 640
height: 480
visible: true
title: qsTr("QML Anchors Review")
color: "#303030"
Rectangle {
id: blueRectangle
color: "#008080"
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 30
height: 320
}
Rectangle {
id: greenRectangle
color: "#3CB371"
anchors.top: blueRectangle.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 30
}
}

Еще по плану было разобрать AnchorChanges, но опять же хочется не несколькими общими предложениями отделаться, а наглядные примеры рассмотреть, поэтому оставлю до следующей статьи.




Понравилось как все доступно вы описываете. Жду следующую статью о AnchorChanges.