Spec-Zone.ru › Qt 5.13

Атрибуты объектов QML

Каждый тип QML-объекта имеет определённый набор атрибутов. Каждый экземпляр типа объекта создаётся с набором атрибутов, определённых для этого типа объекта. Ниже описаны несколько различных типов атрибутов.

Атрибуты в объявлениях объектов

Объявление объекта в документе QML определяет новый тип. Оно также объявляет иерархию объектов, которая будет инициализирована при создании экземпляра этого нового типа.

Набор типов атрибутов QML-объектов следующий:

  • атрибут id
  • атрибуты свойств
  • атрибуты сигналов
  • атрибуты обработчиков сигналов
  • атрибуты методов
  • прикреплённые свойства и прикреплённые обработчики сигналов
  • атрибуты перечислений

Эти атрибуты подробно обсуждаются ниже.

Атрибут id

Каждый тип QML-объекта имеет ровно один атрибут id. Этот атрибут предоставляется самим языком и не может быть переопределён или изменён никаким типом QML-объекта.

Значение может быть присвоено атрибуту id экземпляра объекта, чтобы позволить другим объектам идентифицировать и ссылаться на этот объект. Это значение id должно начинаться с маленькой буквы или символа подчёркивания и не может содержать символы, отличные от букв, цифр и символов подчёркивания.

Ниже приведены объект TextInput и объект Text. Значение атрибута id объекта TextInput установлено в «myTextInput». Объект Text устанавливает своё свойство text с тем же значением, что и свойство text объекта TextInput, ссылаясь на myTextInput.text. Теперь оба элемента будут отображать одинаковый текст:

import QtQuick 2.0

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

К объекту можно обратиться по его id из любой точки области видимости компонента, в которой он объявлен. Следовательно, значение id должно всегда быть уникальным в пределах области видимости компонента. Дополнительную информацию см. в разделе Область видимости и разрешение имён.

После создания экземпляра объекта значение его атрибута id изменить нельзя. Хотя он может выглядеть как обычное свойство, атрибут id не является обычным атрибутом property, и для него применяются специальные семантические правила; например, получить myTextInput.id в приведённом выше примере невозможно.

Атрибуты свойств

Свойство — это атрибут объекта, которому можно присвоить статическое значение или привязать его к динамическому выражению. Значение свойства может быть прочитано другими объектами. Обычно его также может изменить другой объект, если конкретный тип QML не запретил это для определённого свойства.

Определение атрибутов свойств

Свойство может быть определено для типа в C++ путём регистрации свойства Q_PROPERTY класса, которое затем регистрируется в системе типов QML. Кроме того, пользовательское свойство типа объекта может быть определено в объявлении объекта в документе QML со следующим синтаксисом:

[default] property <propertyType> <propertyName>

Таким образом, объявление объекта может экспонировать определённое значение для внешних объектов или проще поддерживать внутреннее состояние.

Имена свойств должны начинаться с маленькой буквы и могут содержать только буквы, цифры и символы подчёркивания. Зарезервированные слова JavaScript не являются допустимыми именами свойств. Ключевое слово default является необязательным и изменяет семантику объявляемого свойства. Дополнительную информацию об атрибуте свойства default см. в следующем разделе о свойствах по умолчанию.

Объявление пользовательского свойства неявно создаёт сигнал изменения значения для этого свойства, а также связанный с ним обработчик сигналов on<ИмяСвойства>Changed, где <ИмяСвойства> — это имя свойства с заглавной первой буквой.

Например, следующее объявление объекта определяет новый тип, который наследуется от базового типа Rectangle. Он имеет два новых свойства, и для одного из них реализован обработчик сигналов:

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}
Допустимые типы в определениях пользовательских свойств

В качестве типов пользовательских свойств можно использовать любые из базовых типов QML, кроме типа перечисления. Например, все эти объявления свойств являются допустимыми:

Item {
    property int someNumber
    property string someString
    property url someUrl
}

(Значения перечисления — это просто целочисленные значения, и вместо типа int можно использовать тип int.)

Некоторые базовые типы предоставляются модулем QtQuick, и поэтому они не могут использоваться в качестве типов свойств без импорта модуля. Дополнительную информацию см. в документации по базовым типам QML.

Обратите внимание, что базовый тип var является универсальным плейсхолдером, который может содержать любой тип значения, включая списки и объекты:

property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }

Кроме того, в качестве типа свойства можно использовать любой тип QML-объекта. Например:

property Item someItem
property Rectangle someRectangle

Это также относится к пользовательским типам QML. Если тип QML был определён в файле с именем ColorfulButton.qml (в каталоге, импортированном клиентом), то свойство типа ColorfulButton также будет допустимым.

Присвоение значений атрибутам свойств

Значение свойства экземпляра объекта можно указать двумя способами:

  • присвоение значения при инициализации
  • императивное присвоение значения

В обоих случаях значение может быть либо статическим, либо выражением привязки.

Присвоение значения при инициализации

Синтаксис присвоения значения свойству при инициализации:

<propertyName> : <value>

Если необходимо, присвоение начального значения свойства можно объединить с определением свойства в объявлении объекта. В этом случае синтаксис определения свойства становится следующим:

[default] property <propertyType> <propertyName> : <value>

Следующий пример показывает инициализацию значения свойства:

import QtQuick 2.0

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}
Императивное присвоение значения

Императивное присвоение значения — это присвоение значения свойства (статического значения или выражения привязки) из императивного кода JavaScript. Синтаксис императивного присвоения значения — это просто оператор присваивания JavaScript, как показано ниже:

[<objectId>.]<propertyName> = value

Следующий пример показывает императивное присвоение значения:

import QtQuick 2.0

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

Статические значения и значения выражений привязки

Как уже отмечалось, для свойства можно присвоить два типа значений: статические и выражения привязки. Последние также известны как связи свойств.

Вид Семантика
Статическое значение Постоянное значение, которое не зависит от других свойств.
Выражение привязки Выражение JavaScript, описывающее взаимосвязь свойства с другими свойствами. Переменные в этом выражении называются зависимостями свойства.

Двигатель QML обеспечивает взаимосвязь между свойством и его зависимостями. При изменении значения любой зависимости движок QML автоматически переоценивает выражение привязки и присваивает новый результат свойству.

В этом примере показано присвоение обоих типов значений свойствам:

import QtQuick 2.0

Rectangle {
    // both of these are static value assignments on initialization
    width: 400
    height: 200

    Rectangle {
        // both of these are binding expression value assignments on initialization
        width: parent.width / 2
        height: parent.height
    }
}

Примечание: Чтобы императивно присвоить выражение привязки, выражение привязки должно быть заключено в функцию, которая передаётся в Qt.binding(), а затем значение, возвращаемое Qt.binding(), должно быть присвоено свойству. В отличие от этого, Qt.binding() не следует использовать при присваивании выражения привязки при инициализации. Дополнительную информацию см. в разделе Связь свойств.

Безопасность типов

Свойства безопасны с точки зрения типов. Свойству можно присвоить только значение, соответствующее типу свойства.

Например, если свойство — это вещественное число, и вы попытаетесь присвоить ему строку, получите ошибку:

property int volume: "four"  // generates an error; the property's object will not be loaded

Аналогично, если во время выполнения свойству присваивается значение неверного типа, новое значение не будет присвоено, и будет сгенерирована ошибка.

Для некоторых типов свойств нет естественного представления значения, и в таких случаях движок QML автоматически выполняет преобразование строки в значение типа. Таким образом, например, даже если свойства типа color хранят цвета, а не строки, вы можете присвоить строку "red" свойству цвета без сообщения об ошибке.

Список типов свойств, поддерживаемых по умолчанию, см. в базовых типах QML. Кроме того, в качестве типа свойства также можно использовать любой доступный тип QML-объекта.

Специальные типы свойств

Атрибуты свойств типа списка объектов

Свойству типа список можно присвоить список значений QML-объектов. Синтаксис для определения значения списка объектов — это список значений, разделённых запятыми, заключённый в квадратные скобки:

[ <item 1>, <item 2>, ... ]

Например, тип Item имеет свойство states, которое используется для хранения списка объектов типа State. В приведенном ниже коде значение этого свойства инициализируется списком из трёх объектов State:

import QtQuick 2.0

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

Если список содержит один элемент, квадратные скобки можно опустить:

import QtQuick 2.0

Item {
    states: State { name: "running" }
}

Свойство типа список можно указать в объявлении объекта следующим образом:

[default] property list<<objectType>> propertyName

и, как и другие объявления свойств, объявление свойства с инициализацией может быть объединено следующим образом:

[default] property list<<objectType>> propertyName: <value>

Следующий пример показывает объявление свойства списка:

import QtQuick 2.0

Rectangle {
    // declaration without initialization
    property list<Rectangle> siblingRects

    // declaration with initialization
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

Если вы хотите объявить свойство для хранения списка значений, которые не обязательно являются значениями QML-объектов, вместо этого следует объявить свойство типа var.

Сгруппированные свойства

В некоторых случаях свойства содержат логическую группу атрибутов подсвойств. Эти атрибуты подсвойств можно назначать, используя либо обозначение точкой, либо обозначение группы.

Например, тип Text имеет групповое свойство font. Ниже, первый объект Text инициализирует свои font значения с помощью обозначения точкой, а второй — с помощью обозначения группы:

Text {
    //dot notation
    font.pixelSize: 12
    font.b: true
}

Text {
    //group notation
    font { pixelSize: 12; b: true }
}

Групповые типы свойств — это базовые типы, имеющие подсвойства. Некоторые из этих базовых типов предоставляются языком QML, в то время как другие могут использоваться только при импорте модуля Qt Quick. Для получения дополнительной информации см. документацию о базовых типах QML.

Псевдонимы свойств

Псевдонимы свойств — это свойства, которые содержат ссылку на другое свойство. В отличие от обычного определения свойства, которое выделяет новое, уникальное хранилище для свойства, псевдоним свойства связывает вновь объявленное свойство (называемое псевдонимом свойства) как прямую ссылку на существующее свойство (называемое связанным свойством).

Объявление псевдонима свойства выглядит как обычное определение свойства, за исключением того, что оно требует ключевого слова alias, а не типа свойства, и правая часть объявления свойства должна быть допустимой ссылкой на псевдоним:

[default] property alias <name>: <alias reference>

В отличие от обычного свойства, псевдоним имеет следующие ограничения:

  • Он может ссылаться только на объект или свойство объекта, которое находится в области видимости типа type, в котором объявлен псевдоним.
  • Он не может содержать произвольные выражения JavaScript.
  • Он не может ссылаться на объекты, объявленные за пределами области видимости его типа.
  • Ссылка на псевдоним не является необязательной, в отличие от необязательного значения по умолчанию для обычного свойства; ссылка на псевдоним должна быть предоставлена при первом объявлении псевдонима.
  • Он не может ссылаться на присоединённые свойства.
  • Он не может ссылаться на групповые свойства; следующий код не будет работать:
    property alias color: rectangle.border.color
    
    Rectangle {
        id: rectangle
    }

    Однако псевдонимы для свойств типа значение работают:

    property alias rectX: object.rectProperty.x
    
    Item {
        id: object
        property rect rectProperty
    }

Например, ниже представлен тип Button с алиасом свойства buttonText, который связан с объектом text дочернего объекта Text:

// Button.qml
import QtQuick 2.0

Rectangle {
    property alias buttonText: textItem.text

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

Следующий код создаст Button с определённой строкой текста для дочернего объекта Text:

Button { buttonText: "Click Me" }

Здесь изменение buttonText непосредственно изменяет значение textItem.text; оно не изменяет какое-либо другое значение, которое затем обновляет textItem.text. Если buttonText не был псевдонимом, изменение его значения фактически не изменило бы отображаемый текст, поскольку привязки свойств не являются двунаправленными: значение buttonText изменилось бы, если бы изменилось значение textItem.text, но не наоборот.

Учитываемые моменты при использовании псевдонимов свойств

Псевдонимы активируются только после полной инициализации компонента. При попытке обратиться к неинициализированному псевдониму генерируется ошибка. Аналогично, использование псевдонима псевдонима свойства также приведёт к ошибке.

property alias widgetLabel: label

//will generate an error
//widgetLabel.text: "Initial text"

//will generate an error
//property alias widgetLabelText: widgetLabel.text

Component.onCompleted: widgetLabel.text = "Alias completed Initialization"

Однако при импорте типа QML-объекта с псевдонимом свойства в корневом объекте, свойство появляется как обычное свойство Qt и, следовательно, может использоваться в ссылках на псевдонимы.

Возможно, что свойство-псевдоним имеет то же имя, что и существующее свойство, эффективно перезаписывая существующее свойство. Например, следующий тип QML имеет свойство-псевдоним color, имеющее то же имя, что и встроенное свойство Rectangle::color:

Rectangle {
    id: coloredrectangle
    property alias color: bluerectangle.color
    color: "red"

    Rectangle {
        id: bluerectangle
        color: "#1234ff"
    }

    Component.onCompleted: {
        console.log (coloredrectangle.color)    //prints "#1234ff"
        setInternalColor()
        console.log (coloredrectangle.color)    //prints "#111111"
        coloredrectangle.color = "#884646"
        console.log (coloredrectangle.color)    //prints #884646
    }

    //internal function that has access to internal properties
    function setInternalColor() {
        color = "#111111"
    }
}

Любой объект, использующий этот тип и ссылающийся на его свойство color, будет ссылаться на псевдоним, а не на обычное свойство Rectangle::color. Однако внутренне прямоугольник может правильно установить своё свойство color и ссылаться на фактически определённое свойство, а не на псевдоним.

Псевдонимы свойств и типы

Псевдонимы свойств не могут иметь явных указаний типа. Тип псевдонима свойства — это объявленный тип свойства или объекта, на который он ссылается. Поэтому, если вы создаёте псевдоним для объекта, на который ссылаются по id с дополнительными свойствами, объявленными в строке, дополнительные свойства не будут доступны через псевдоним:

// MyItem.qml
Item {
    property alias inner: innerItem

    Item {
        id: innerItem
        property int extraProperty
    }
}

Вы не можете инициализировать inner.extraProperty извне этого компонента, так как inner — это только Item:

// main.qml
MyItem {
    inner.extraProperty: 5 // fails
}

Однако, если вы вынесете внутренний объект в отдельный компонент с отдельным файлом .qml, вы можете вместо этого создать экземпляр этого компонента и иметь все его свойства доступными через псевдоним:

// MainItem.qml
Item {
    // Now you can access inner.extraProperty, as inner is now an ExtraItem
    property alias inner: innerItem

    ExtraItem {
        id: innerItem
    }
}

// ExtraItem.qml
Item {
    property int extraProperty
}

Свойства по умолчанию

Определение объекта может иметь единственное свойство по умолчанию. Свойство по умолчанию — это свойство, которому присваивается значение, если объект объявлен внутри определения другого объекта, без его объявления как значения для конкретного свойства.

Объявление свойства с необязательным ключевым словом default отмечает его как свойство по умолчанию. Например, пусть в файле MyLabel.qml есть свойство по умолчанию someText:

// MyLabel.qml
import QtQuick 2.0

Text {
    default property var someText

    text: "Hello, " + someText.text
}

Значение someText можно присвоить в определении объекта MyLabel следующим образом:

MyLabel {
    Text { text: "world!" }
}

Это имеет точно такой же эффект, как и следующее:

MyLabel {
    someText: Text { text: "world!" }
}

Однако, поскольку свойство someText помечено как свойство по умолчанию, нет необходимости явно назначать объект Text этому свойству.

Вы заметите, что дочерние объекты могут быть добавлены к любому типу, основанному на Item, без явного добавления их к свойству children. Это происходит потому, что свойством по умолчанию для Item является его свойство data , и все элементы, добавленные в этот список для Item, автоматически добавляются в его список children.

Свойства по умолчанию могут быть полезны для повторного назначения дочерних элементов элемента. См. Пример TabWidget, который использует свойство по умолчанию для автоматического повторного назначения дочерних элементов TabWidget в качестве дочерних элементов внутреннего ListView. См. также Расширение QML.

Только для чтения свойства

Определение объекта может определить свойство только для чтения, используя ключевое слово readonly, со следующим синтаксисом:

readonly property <propertyType> <propertyName> : <initialValue>

Свойствам только для чтения необходимо присвоить значение при инициализации. После инициализации свойство только для чтения больше нельзя присваивать значение, как с помощью императивного кода, так и иными способами.

Например, код в блоке Component.onCompleted ниже недействителен:

Item {
    readonly property int someNumber: 10

    Component.onCompleted: someNumber = 20  // doesn't work, causes an error
}

Примечание: Свойство только для чтения не может быть также свойством по умолчанию.

Объекты-модификаторы свойств

Свойства могут иметь объекты-модификаторы значений свойств, связанные с ними. Синтаксис объявления экземпляра типа модификатора свойства, связанного с конкретным свойством, выглядит следующим образом:

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

Важно отметить, что указанный синтаксис фактически представляет собой объявление объекта, которое создаст объект, который будет действовать на существующее свойство.

Некоторые типы модификаторов свойств могут применяться только к определённым типам свойств, однако язык этого не проверяет. Например, тип NumberAnimation , предоставляемый QtQuick, будет анимировать только числовые свойства (такие как int или real). Попытка использовать NumberAnimation с нечисловым свойством не приведёт к ошибке, однако нечисловое свойство не будет анимировано. Поведение типа модификатора свойства при связывании с конкретным типом свойства определяется его реализацией.

Атрибуты сигнала

Сигнал — это уведомление от объекта о том, что произошло какое-то событие: например, изменилось свойство, началась или остановилась анимация или загрузилось изображение. Тип MouseArea, например, имеет сигнал clicked, который излучается при нажатии пользователем внутри области мыши.

Объект может получать уведомление через обработчик сигнала всякий раз, когда излучается определённый сигнал. Обработчик сигнала объявляется с синтаксисом on<Signal>, где <Signal> — это имя сигнала с заглавной первой буквой. Обработчик сигнала должен быть объявлен внутри определения объекта, который излучает сигнал, и обработчик должен содержать блок кода JavaScript, который должен быть выполнен при вызове обработчика сигнала.

Например, обработчик сигнала onClicked ниже объявлен внутри объекта MouseArea и вызывается при нажатии на MouseArea, вызывая вывод сообщения в консоль:

import QtQuick 2.0

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

Определение атрибутов сигнала

Сигнал может быть определён для типа на C++ путём регистрации Q_SIGNAL класса, который затем регистрируется в системе типов QML. Альтернативно, пользовательский сигнал для типа объекта может быть определён в объявлении объекта в документе QML со следующим синтаксисом:

signal <signalName>[([<type> <parameter name>[, ...]])]

Попытка объявить два сигнала или метода с одинаковым именем в одном блоке типа является ошибкой. Однако новый сигнал может повторно использовать имя существующего сигнала в типе. (Это следует делать с осторожностью, поскольку существующий сигнал может быть скрыт и стать недоступным.)

Вот три примера объявлений сигналов:

import QtQuick 2.0

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(string action, var actionResult)
}

Если у сигнала нет параметров, скобки «()» необязательны. Если используются параметры, типы параметров должны быть объявлены, как для аргументов string и var для сигнала actionPerformed выше. Допустимые типы параметров такие же, как перечисленные в разделе Определение атрибутов свойства на этой странице.

Для излучения сигнала вызывается метод. Любые соответствующие обработчики сигнала будут вызваны при излучении сигнала, и обработчики могут использовать определённые имена аргументов сигнала для доступа к соответствующим аргументам.

Сигналы изменения свойства

Типы QML также предоставляют встроенные сигналы изменения свойств, которые испускаются всякий раз, когда значение свойства изменяется, как описано ранее в разделе о атрибутах свойств. Подробности об использовании этих сигналов и о том, как ими пользоваться, см. в следующем разделе о обработчиках сигналов изменения свойств.

Атрибуты обработчиков сигналов

Обработчики сигналов — это особый вид атрибута метода, где реализация метода вызывается движком QML всякий раз, когда испускается связанный сигнал. Добавление сигнала в определение объекта в QML автоматически добавит связанный обработчик сигнала в определение объекта, который по умолчанию имеет пустую реализацию. Клиенты могут предоставить реализацию для реализации логики программы.

Рассмотрим следующий SquareButton тип, определение которого приведено в файле SquareButton.qml в виде, показанном ниже, с сигналами activated и deactivated:

// SquareButton.qml
Rectangle {
    id: root

    signal activated(real xPosition, real yPosition)
    signal deactivated

    property int side: 100
    width: side; height: side

    MouseArea {
        anchors.fill: parent
        onPressed: root.activated(mouse.x, mouse.y)
        onReleased: root.deactivated()
    }
}

Эти сигналы могут быть получены любыми SquareButton объектами в другом файле QML в том же каталоге, где реализации обработчиков сигналов предоставляются клиентом:

// myapplication.qml
SquareButton {
    onActivated: console.log("Activated at " + xPosition + "," + yPosition)
    onDeactivated: console.log("Deactivated!")
}

Дополнительную информацию об использовании сигналов см. в разделе Системы событий сигналов и обработчиков.

Обработчики сигналов изменения свойств

Обработчики сигналов изменения свойств имеют синтаксическую форму on<Свойство>Changed, где <Свойство> — имя свойства, первая буква которого заглавная. Например, хотя документация типа TextInput не документирует сигнал textChanged, этот сигнал неявно доступен благодаря тому, что у TextInput есть свойство text, поэтому можно написать обработчик сигнала onTextChanged, который вызывается всякий раз, когда это свойство изменяется:

import QtQuick 2.0

TextInput {
    text: "Change this!"

    onTextChanged: console.log("Text has changed to:", text)
}

Атрибуты методов

Метод типа объекта — это функция, которую можно вызвать для выполнения некоторой обработки или запуска других событий. Метод может быть подключен к сигналу, так что он автоматически вызывается всякий раз, когда испускается сигнал. Подробности см. в разделе Системы событий сигналов и обработчиков.

Определение атрибутов методов

Метод для типа в C++ может быть определен, пометив функцию класса, которая затем регистрируется в системе типов QML с помощью Q_INVOKABLE, или зарегистрировав её как Q_SLOT класса. Кроме того, пользовательский метод может быть добавлен к объявлению объекта в документе QML с помощью следующего синтаксиса:

function <functionName>([<parameterName>[, ...]]) { <body> }

Методы могут быть добавлены к типу QML для определения автономных, многократно используемых блоков кода JavaScript. Эти методы можно вызывать как внутри объекта, так и извне.

В отличие от сигналов, типы параметров методов не нужно объявлять, так как они по умолчанию имеют тип var.

Попытка объявить два метода или сигнала с одинаковым именем в одном блоке типа является ошибкой. Однако новый метод может повторно использовать имя существующего метода типа. (Это следует делать с осторожностью, так как существующий метод может быть скрыт и станет недоступным.)

Ниже приведен пример Rectangle с методом calculateHeight(), который вызывается при присвоении значения height:

import QtQuick 2.0
Rectangle {
    id: rect

    function calculateHeight() {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

Если метод имеет параметры, они доступны по имени внутри метода. Ниже, когда MouseArea нажимается, он вызывает метод moveTo(), который может ссылаться на полученные параметры newX и newY для перепозиционирования текста:

import QtQuick 2.0

Item {
    width: 200; height: 200

    MouseArea {
        anchors.fill: parent
        onClicked: label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label

        function moveTo(newX, newY) {
            label.x = newX;
            label.y = newY;
        }

        text: "Move me!"
    }
}

Присоединённые свойства и присоединённые обработчики сигналов

Присоединённые свойства и присоединённые обработчики сигналов — это механизмы, которые позволяют аннотировать объекты дополнительными свойствами или обработчиками сигналов, которые в противном случае недоступны объекту. В частности, они позволяют объектам получать доступ к свойствам или сигналам, которые специфичны для данного объекта.

Реализация типа QML может выбрать создание типа присоединения в C++ с определёнными свойствами и сигналами. Затем экземпляры этого типа могут быть созданы и присоединены к конкретным объектам во время выполнения, позволяя этим объектам получить доступ к свойствам и сигналам типа присоединения. К ним обращаются, добавляя имя типа присоединения как префикс к свойствам и соответствующим обработчикам сигналов.

Ссылки на присоединённые свойства и обработчики имеют следующий синтаксис:

<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>

Например, тип ListView имеет присоединённое свойство ListView.isCurrentItem, доступное каждому объекту делегата в ListView. Это можно использовать каждому отдельному объекту делегата для определения, является ли он текущим выбранным элементом в представлении:

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

В этом случае имя типа присоединения — ListView, а интересующее свойство — isCurrentItem, поэтому к присоединённому свойству обращаются как ListView.isCurrentItem.

Присоединённый обработчик сигнала указывается аналогичным образом. Например, присоединённый обработчик сигнала Component.onCompleted часто используется для выполнения некоторого кода JavaScript, когда процесс создания компонента завершён. В примере ниже, после того, как ListModel был полностью создан, его обработчик сигнала Component.onCompleted автоматически вызывается для заполнения модели:

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: ListModel {
        id: listModel
        Component.onCompleted: {
            for (var i = 0; i < 10; i++)
                listModel.append({"Name": "Item " + i})
        }
    }
    delegate: Text { text: index }
}

Поскольку имя типа присоединения — Component, а у этого типа есть сигнал completed, присоединённый обработчик сигнала называется Component.onCompleted.

Примечание об обращении к присоединённым свойствам и обработчикам сигналов

Распространённая ошибка заключается в предположении, что присоединённые свойства и обработчики сигналов непосредственно доступны для потомков объекта, к которому эти атрибуты были присоединены. Это не так. Экземпляр типа присоединения присоединён только к конкретным объектам, а не к объекту и всем его потомкам.

Например, ниже приведён изменённый вариант предыдущего примера, касающегося присоединённых свойств. На этот раз делегат — Item, а цветной Rectangle — дочерний элемент этого элемента:

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Item {
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: ListView.isCurrentItem ? "red" : "yellow"    // WRONG! This won't work.
        }
    }
}

Это не работает как ожидалось, потому что ListView.isCurrentItem присоединён только к корневому объекту делегата, а не к его потомкам. Поскольку Rectangle является потомком делегата, а не самим делегатом, он не может получить доступ к присоединённому свойству isCurrentItem как ListView.isCurrentItem. Поэтому вместо этого прямоугольник должен получить доступ к isCurrentItem через корневой делегат:

ListView {
    //....
    delegate: Item {
        id: delegateItem
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: delegateItem.ListView.isCurrentItem ? "red" : "yellow"   // correct
        }
    }
}

Теперь delegateItem.ListView.isCurrentItem правильно ссылается на присоединённое свойство isCurrentItem делегата.

Атрибуты перечислений

Перечисления предоставляют фиксированный набор именованных вариантов. Они могут быть объявлены в QML с использованием ключевого слова enum:

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }
}

Как показано выше, типы перечислений (например, TextType) и значения (например, Normal) должны начинаться с заглавной буквы.

К значениям обращаются через <Type>.<EnumerationType>.<Value> или <Type>.<Value>.

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }

    property int textType: MyText.TextType.Normal

    font.bold: textType == MyText.TextType.Heading
    font.pixelSize: textType == MyText.TextType.Heading ? 24 : 12
}

Дополнительную информацию об использовании перечислений в QML см. в документации QML Basic Types enumeration.

Возможность объявлять перечисления в QML была добавлена в Qt 5.10.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/qtqml-syntax-objectattributes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API