Top.Mail.Ru

Qt. QML Anchors. Позиционирование элементов.

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

QML 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.fill

Аналогичного эффекта можно было добиться так:

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

Описание QML anchors

Как и в случае с 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

Результат закономерен с учетом вышеописанного:

Пример anchors на QML

QML Anchors. Margins, offsets.

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

QML anchors margin

То есть 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
    }
}
Пример с anchors.margins

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

Подписаться
Уведомление о
guest
1 Комментарий
старее
новее
Inline Feedbacks
View all comments
Андрей С.
3 месяцев назад

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

1
0
Would love your thoughts, please comment.x
()
x