Сначало опишем представление нашей кнопки в файле 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 == index2) Сначала в 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.