Крім традиційних 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 . Якщо ви хочете змінити якорне позиціонування на абсолютне, значення якоря необхідно очистити.