Определение типов объектов с помощью документов QML
Одна из ключевых особенностей QML заключается в том, что она позволяет легко определять типы объектов QML в лёгком формате с помощью документов QML, чтобы удовлетворить потребности отдельных приложений QML. Стандартный модуль Qt Quick предоставляет различные типы, такие как Прямоугольник, Текст и Изображение для создания приложения QML; помимо этого, вы можете легко определять свои собственные типы QML для повторного использования в вашем приложении. Эта возможность создания собственных типов является основой любого приложения QML.
Определение типа объекта с помощью файла QML
Именование пользовательских типов объектов QML
Для создания типа объекта документ QML должен быть помещён в текстовый файл с именем <TypeName>.qml, где <TypeName> — желаемое имя типа. Имя типа должно соответствовать следующим требованиям:
- Оно должно состоять из буквенно-цифровых символов или символов подчеркивания.
- Оно должно начинаться с заглавной буквы.
Этот документ автоматически распознаётся движком как определение типа QML. Кроме того, тип, определённый таким образом, автоматически становится доступным для других файлов QML в той же директории, так как движок ищет в непосредственной директории при разрешении имён типов QML.
Определение пользовательского типа QML
Например, ниже приведён документ, который объявляет прямоугольник с дочерним элементом MouseArea. Документ был сохранён в файле с именем SquareButton.qml:
// SquareButton.qml
import QtQuick 2.0
Rectangle {
property int side: 100
width: side; height: side
color: "red"
MouseArea {
anchors.fill: parent
onClicked: console.log("Button clicked!")
}
} Поскольку файл имеет имя SquareButton.qml, его можно использовать как тип с именем SquareButton в любом другом файле QML в той же директории. Например, если в той же директории был файл myapplication.qml, он мог бы ссылаться на тип SquareButton:
// myapplication.qml
import QtQuick 2.0
SquareButton {} Это создаёт красный прямоугольник размером 100x100 с внутренним MouseArea, как определено в SquareButton.qml. Когда этот myapplication.qml документ загружается движком, он загружает документ SquareButton.qml как компонент и создаёт объект SquareButton.
Тип SquareButton инкапсулирует дерево объектов QML, объявленных в SquareButton.qml. Когда движок QML создаёт объект SquareButton из этого типа, он создаёт объект из дерева прямоугольников, объявленного в SquareButton.qml.
Примечание: регистр букв имени файла имеет значение на некоторых (особенно UNIX) файловых системах. Рекомендуется, чтобы регистр имени файла точно соответствовал регистру желаемого имени типа QML — например, Box.qml, а не BoX.qml — независимо от платформы, на которой будет развернут тип QML.
Встроенные компоненты
Иногда неудобно создавать новый файл для типа, например, при повторном использовании небольшого делегата в нескольких представлениях. Если вам не нужно экспортировать тип, а только создать экземпляр, Component является вариантом. Но если вы хотите объявлять свойства с типами компонентов или использовать его в нескольких файлах, Component не подходит. В этом случае вы можете использовать встроенные компоненты. Встроенные компоненты объявляют новый компонент внутри файла. Синтаксис для этого:
component <component name> : BaseType {
// declare properties and bindings here
} В файле, который объявляет встроенный компонент, к типу можно обратиться просто по его имени.
// Images.qml
import QtQuick 2.15
Item {
component LabeledImage: Column {
property alias source: image.source
property alias caption: text.text
Image {
id: image
width: 50
height: 50
}
Text {
id: text
font.bold: true
}
}
Row {
LabeledImage {
id: before
source: "before.png"
caption: "Before"
}
LabeledImage {
id: after
source: "after.png"
caption: "After"
}
}
property LabeledImage selectedImage: before
} В других файлах нужно использовать префикс с именем содержащего компонента.
// LabeledImageBox.qml
import QtQuick 2.15
Rectangle {
property alias caption: image.caption
property alias source: image.source
border.width: 2
border.color: "black"
Images.LabeledImage {
id: image
}
} Примечание: Встроенные компоненты не разделяют область видимости с компонентом, в котором они объявлены. В приведенном ниже примере, когда A.MyInlineComponent в файле B.qml создаётся, произойдёт ошибка ReferenceError, так как root не существует как идентификатор в B.qml. Поэтому рекомендуется не ссылаться на объекты во встроенном компоненте, которые не являются частью его.
// A.qml
import QtQuick 2.15
Item {
id: root
property string message: "From A"
component MyInlineComponent : Item {
Component.onCompleted: console.log(root.message)
}
}
// B.qml
import QtQuick 2.15
Item {
A.MyInlineComponent {}
} Примечание: Встроенные компоненты не могут быть вложены.
Импорт типов, определённых вне текущей директории
Если SquareButton.qml не находился в той же директории, что и myapplication.qml, типу SquareButton необходимо сделать доступным через инструкцию import в myapplication.qml. Он может быть импортирован из относительного пути на файловой системе или как установленный модуль; см. модуль для получения дополнительной информации.
Доступные атрибуты пользовательских типов
Определение корневого объекта в файле .qml определяет атрибуты, доступные для типа QML. Все свойства, сигналы и методы, принадлежащие этому корневому объекту — будь то пользовательские объявления или свойства типа корневого объекта QML — являются внешне доступными и могут быть прочитаны и изменены для объектов этого типа.
Например, типом корневого объекта в файле SquareButton.qml выше является прямоугольник. Это означает, что любые свойства, определённые типом прямоугольника, могут быть изменены для объекта SquareButton. Нижеприведённый код определяет три SquareButton объекта с настроенными значениями для некоторых свойств корневого объекта Прямоугольник типа SquareButton:
// application.qml
import QtQuick 2.0
Column {
SquareButton { side: 50 }
SquareButton { x: 50; color: "blue" }
SquareButton { radius: 10 }
} Атрибуты, доступные объектам пользовательского типа QML, включают любые пользовательские свойства, методы и сигналы, которые дополнительно были определены для объекта. Например, предположим, что прямоугольник в SquareButton.qml был определён следующим образом с дополнительными свойствами, методами и сигналами:
// SquareButton.qml
import QtQuick 2.0
Rectangle {
id: root
property bool pressed: mouseArea.pressed
signal buttonClicked(real xPos, real yPos)
function randomizeColor() {
root.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
}
property int side: 100
width: side; height: side
color: "red"
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: (mouse)=> root.buttonClicked(mouse.x, mouse.y)
}
} Любой объект SquareButton может использовать свойство pressed, сигнал buttonClicked и метод randomizeColor(), добавленные к корневому прямоугольнику:
// application.qml
import QtQuick 2.0
SquareButton {
id: squareButton
onButtonClicked: (xPos, yPos)=> {
console.log("Clicked", xPos, yPos)
randomizeColor()
}
Text { text: squareButton.pressed ? "Down" : "Up" }
} Обратите внимание, что любые значения id , определённые в SquareButton.qml, недоступны для объектов SquareButton, так как значения id доступны только в области видимости компонента, в котором объявлен компонент. Объект SquareButton выше не может ссылаться на mouseArea для ссылки на дочерний элемент MouseArea, и если у него был бы идентификатор id со значением root вместо squareButton, это не конфликтовало бы со значением id корневого объекта, определённого в SquareButton.qml, так как оба значения объявлены в разных областях видимости.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qtqml-documents-definetypes.html