Evgenii Legotckoi
10 листопада 2015 р. 19:06

QML - Урок 013. Позиціонування за допомогою якорів

Крім традиційних Grid, Row, Column, Qt Quick також надає функціонал для елементів шарів, що використовує концепцію якорів ( Anchors ). Кожен елемент може бути розглянутий як має набір з 7 невидимих "якорних ліній":

  • left;
  • horizontalCenter;
  • right;
  • top;
  • verticalCenter;
  • baseline;
  • bottom.

Baseline (на даному малюнку) відповідає уявлюваної лінії, де міститься текст. Для елементів без тексту це відповідає лінії top.


Система якорів Qt Quick дозволяє визначати взаємовідносини між якірними лініями різних елементів. Наприклад, Ви можете написати:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; ... }

У цьому випадку, ліва сторона rect2 буде пов'язана з правою стороною rect1, і виглядатиме так:

Ви можете вказати кілька якорів. Наприклад:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }

Вказуючи кілька горизонтальних або вертикальних якорів, можна контролювати розмір елемента. На малюнку нижче, rect2 пов'язаний якорем з rect1 з правого боку та з rect3 з лівого боку. Якщо якийсь із синіх прямокутників пересунути, то rect2 розтягнеться або стиснеться відповідно:

Є також деякий зручний функціонал якорів, наприклад, anchors.fill, котрий встановлює left, right, top та bottom якоря до цільового елементу. anchors.centerIn аналогічний використанню verticalCenter та horizontalCenter одночасно щодо цільового елемента. Тобто встановлює інший елемент центру цільового елемента.

Anchors Margins (Поля) та Offsets (зміщення)

Система якорів також дозволяє встановлювати поля та зміщення для зазначених якорів елементів. Поля вказують порожній простір, який має бути між якорною лінією та елементом, тоді як зсув дозволяє керувати позиціонуванням за допомогою центру якірних ліній. Елемент може вказати поля індивідуально для кожного якоря через leftMargin, rightMargin, topMargin, bottomMargin або використовувати anchors.margins для вказівки значення поля для всіх чотирьох сторін. Зміщення якоря вказуються використанням horizontalCenterOffset, verticalCenterOffset та baselineOffset.**

Наступний приклад вказує left margin:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }

У цьому випадку поле складає 5 пікселів ліворуч від rect2:

Примітка: Поля якорів використовуються тільки для якорів, вони не використовуються стосовно елементів. Тобто, якщо вказано поле (margin) для певної сторони, але елемент не прив'язаний якорем до сторони будь-якого елемента, то поле не застосовується.

Зміна Anchors

Qt Quick надає тип AnchorChanges для уточнення стану якоря.

State {
    name: "anchorRight"
    AnchorChanges {
        target: rect2
        anchors.right: parent.right
        anchors.left: undefined  //remove the left anchor
    }
}

AnchorChanges може бути анімований, використовуючи тип AnchorAnimation.

Transition {
    AnchorAnimation {}  //animates any AnchorChanges in the corresponding state change
}

Якорі також можуть бути змінені безпосередньо за допомогою JavaScript. Однак ці зміни повинні бути здійснені обережно, оскільки можуть призвести до непередбачуваних результатів. Наступний приклад ілюструє проблему:

//bad code
    Rectangle {
        width: 50
        anchors.left: parent.left

        function reanchorToRight() {
            anchors.right = parent.right
            anchors.left = undefined
        }
    }

У прикладі на початку встановлюється правий якір. У той момент, коли лівий та правий якорі встановлені, елемент розтягується по горизонталі свого елемента. Коли лівий якорь видаляється, елемент отримує новий параметр ширини. У результаті параметри ширини об'єкта змінюються, тоді як необхідно зберегти задану ширину об'єкта. Для цього необхідно спочатку видалити лівий якір, а потім встановити правий якір.

 Rectangle {
    width: 50
    anchors.left: parent.left

    function reanchorToRight() {
        anchors.left = undefined
        anchors.right = parent.right
    }
}

Оскільки значення прив'язки не визначені, то не рекомендується змінювати якорі через прив'язки за умовою, оскільки це може призвести до вищезазначеної проблеми. У наступному прикладі прямокутник у результаті розтягнеться на всю ширину свого батька, тому що обидва якорі будуть встановлені одночасно протягом оновлення прив'язок.

//bad code
Rectangle {
    width: 50; height: 50
    anchors.left: state == "right" ? undefined : parent.left;
    anchors.right: state == "right" ? parent.right : undefined;
}

Цей код повинен бути переписаний через AnchorChenges, який буде проводити автоматичну обробку прив'язок якорів.

Обмеження

Для покращення продуктивності ви можете використовувати якір тільки безпосередньо до батьківського елемента або до елементів братів, тобто тих, що лежать у тому ж батьку, що і даний елемент. Наприклад, наступний код є неправильним:

//bad code
Item {
    id: group1
    Rectangle { id: rect1; ... }
}
Item {
    id: group2
    Rectangle { id: rect2; anchors.left: rect1.right; ... }    // invalid anchor!
}

Також шари засновані на якорях не можуть бути змішані з абсолютним позиціонуванням. Якщо елементу вказується його позиція і також встановлюється acnhors.left або додатково до лівого та правого якоря вказується ширина елемента, результат не буде визначений, оскільки не відомо, чи потрібно використовувати якоря або абсолютне позиціонування. Те саме можна сказати про висоту елемента та використання якорів top і bottom, або установку acnhors.fill з установкою висоти або ширини. Те саме відноситься і до встановлення таких об'єктів як Row та Grid, які можуть встановлювати елементи властивості x та y . Якщо ви хочете змінити якорне позиціонування на абсолютне, значення якоря необхідно очистити.

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up