Определение типов объектов через QML-документы
Одной из ключевых функций QML является возможность легко определять типы QML-объектов в QML-документах, приспосабливая их к потребностям отдельных QML-приложений. Стандартный модуль Qt Quick предоставляет различные типы, такие как Прямоугольник, Текст и Изображение для построения QML-приложения; помимо этого, вы можете легко определять собственные QML-типы для повторного использования в приложении. Эта возможность создавать свои собственные типы является основой любого QML-приложения.
Определение типа объекта с помощью QML-файла
Именование пользовательских типов QML-объектов
Для создания типа объекта QML-документ должен быть помещен в текстовый файл с именем <TypeName>.qml, где <TypeName> — желаемое имя типа. Имя типа должно соответствовать следующим требованиям:
- Оно должно состоять из буквенно-цифровых символов или подчеркиваний.
- Оно должно начинаться с заглавной буквы.
Этот документ автоматически распознаётся движком как определение QML-типа. Кроме того, тип, определённый таким образом, автоматически становится доступным для других QML-файлов в той же директории, так как движок ищет в непосредственной директории при разрешении имён QML-типов.
Определение пользовательского типа QML
Например, ниже представлен документ, который объявляет Прямоугольник с дочерним Областью мыши. Документ был сохранён в файл под названием 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 красный Прямоугольник с внутренней Областью мыши, как определено в 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 не существует как id в 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: root.buttonClicked(mouse.x, mouse.y)
}
} Любой объект SquareButton мог бы использовать свойство pressed, сигнал buttonClicked и метод randomizeColor(), которые были добавлены к корневому Прямоугольнику:
// application.qml
import QtQuick 2.0
SquareButton {
id: squareButton
onButtonClicked: {
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.0/qtqml-documents-definetypes.html