Главная

Главная

Сообщество

Сообщество

Форум

Форум

STM32

STM32

Электроника

Электроника

Raspberry Pi

Raspberry Pi

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 Комментарий
Старые
Новые
Андрей С.
4 лет назад

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

Обзор конфиденциальности

На этом сайте используются файлы cookie, что позволяет нам обеспечить наилучшее качество обслуживания пользователей. Информация о файлах cookie хранится в вашем браузере и выполняет такие функции, как распознавание вас при возвращении на наш сайт и помощь нашей команде в понимании того, какие разделы сайта вы считаете наиболее интересными и полезными.