Решил написать для себя небольшую шпаргалку-запоминалку по одному моменту в QML. Всё очень просто и банально, но думаю так в памяти отложиться намного лучше. Задача состоит в следующем: показать как можно создать некоторую коллекцию одинаковых визуальных элементов используя вместе элемент
Column и
Repeater. Я покажу на очень простом примере, без всякой анимации и красивых фичей, просто функционал, плюс будет некоторый хардкодинг.
Сначало опишем представление нашей кнопки в файле Button.qml:
import QtQuick 1.1
Rectangle {
id: button
width: 120
height: 50
signal clicked()
property string text
property bool active: true
states: [
State {
name: "selected"
when: button.active
PropertyChanges {
target: button
color: "Red"
}
}
]
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: button.clicked()
hoverEnabled: true
}
Text {
id: name
text: button.text
font.pointSize: 20
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Тут достаточно всё просто. Кнопка представляет собой обычный прямоугольник
Rectangle размером 120 на 50, в нём находится элемент
MouseArea для обработки событий мыши и обычное текстовое поле
Text, у которого свойство text, связано с определённым мной свойством text у элемента Rectangle (который является его родителем). Так же определено мной свойство active, которое отображает активна кнопка или нет (под активностью я понимаю нажатие на неё). Соответственно, в состоянии "selected":
State {
name: "selected"
when: button.active
PropertyChanges {
target: button
color: "Red"
}
}
я определяю условие наступления этого состояния - button.active должен быть true (и тогда цвет кнопки станет красным), по умолчанию он false.
Далее следует файл main.qml:
Rectangle {
width: 120
height: 150
property variant buttonData: [
{ text: "Button" },
{ text: "Button" },
{ text: "Button" }
]
Column {
id: buttonsLayout
spacing: 5
property int activeButton
Repeater {
model: buttonData
delegate:
Button {
text: modelData.text + index
onClicked: {
buttonsLayout.activeButton = index
}
active: buttonsLayout.activeButton == index
}
}
}
}
Выглядит это примерно следующим образом:
В данном случае используется элемент
Repeater, который позволяет создать группу одинаковых элементов (например, несколько кнопок меню или несколько вкладок), унаследованных от Item. Создаваться эта группа элементов будет в
Column. Как видно на примере выше мы задали 2 свойства: id, spacing и определили своё activeButton, которое будет содержать номер активной кнопки, т.е. нажатой в данный момент времени. А потом мы добавляем элемент Repeater, которому соотносим модель, где хранится описание 3х кнопок, причём в модели кнопки одинаковые. В delegate определяем тот элемент, который будет создавать и вот стоит обратить внимание на свойство
index, доступное только для чтение, это некий счётчик созданных экземпляров. Соответственно в моём примере он используется для двух целей:
1) Добавление номера в надпись:
active: buttonsLayout.activeButton == index
2) Сначала в onClicked мы пишем какое число нужно присвоить внешнему (родительскому) свойству buttonsLayout.activeButton при клике на конкретную кнопку Button. Соответственно, для первой созданной кнопки buttonsLayout.activeButton = 1, для второй buttonsLayout.activeButton = 2, для третьей buttonsLayout.activeButton = 3.
А потом свойство active (это свойство созданного нами элемента Button, типа bool) связываем с условием, при котором index сравниваемым с buttonsLayout.activeButton (для первой созданной кнопки buttonsLayout.activeButton == 1, для второй buttonsLayout.activeButton == 2, для третьей buttonsLayout.activeButton == 3). Когда это выражение будет true, т.е. и свойство active тоже true, соответственно в Button будет сделан переход к состоянию "selected":
State {
name: "selected"
when: button.active
PropertyChanges {
target: button
color: "Red"
}
}
потому что будет выполнено услование when: button.active
Чуть чуть обобщая для лучшего понимания: в onClicked мы говорим какое число присвоить свойству activeButton элемента buttonsLayout, а в active: buttonsLayout.activeButton == index мы говорим какой index будет для каждого элемента и только в уникальном случае для каждого элемента Button, выражение buttonsLayout.activeButton == index будет true и соответственно свойство active тоже будет true.
Всё равно как-то витиевато написал, но главное что сам понял, как можно применять этот достаточно банальный способ, про который не знал ( не знал в первую очерель про свойство index, которые read-only). Если что-то непонятно - пишите в комментариях.
Исходный код примера можно найти на
github.