# Компоненты

Copyright&nbsp;©&nbsp;2016–2023 ООО&nbsp;«Открытая мобильная платформа».
Этот документ предоставляется в&nbsp;соответствии
с&nbsp;[Публичной лицензией Creative Commons с&nbsp;указанием авторства версии&nbsp;4.0 Международная](../../LICENSE.CC-BY-4.0.ru.md).

## Создание собственных QML-компонентов

Библиотеки Qt Quick и Silica предоставляют большой набор компонентов для создания интерфейсов
для приложений на ОС Аврора.
Помимо этого средства QML позволяют создавать собственные компоненты на основе стандартных
для решения более специфических задач внутри приложения.
Такие компоненты могут быть многократно переиспользованы внутри приложения (а также в других приложениях).
Выделение QML кода в отдельные компоненты позволяет увеличить читаемость кода, облегчить его поддержку
и исключить дублирование.

## Создание собственных QML-компонентов [2]

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

Чтобы создать и использовать собственный компонент, выполните следующие действия:

1.	Создайте новый файл TypeName.qml.
	Имейте в виду, что TypeName - это имя компонента, который будет использоваться в других файлах и компонентах.
	Название должно содержать только буквы, цифры и подчеркивания, а также начинаться с заглавной буквы.
2.	Опишите элемент, находящийся в TypeName.qml. У него может быть ровно один корневой элемент.
3.	Там, где вы собираетесь использовать TypeName, импортируйте его, указав путь к директории.
	Например, если на одном уровне с директорией с нашим файлом находится директория assets,
	импотрируйте содержимое assets кодом import "../assets".
4.	Используйте компонент TypeName.

## Пример собственной кнопки

Пример импортированного из соседней директории Button.qml.
Директории assets и pages расположены на одном уровне.

## Пример файлов из одного каталога

Если файлы лежат в одной директории, оператор импорта не нужен.

## Тип Component

Component предназначен для инкапсуляции QML типов с четко определенными интерфейсом
для повторного использования.
В отличии от типов, которые определяются с помощью отдельных файлов с расширением .qml,
элементы Component позволяют определять QML типы в пределах одного файла.
Кроме этого, компоненты QML можно определять через отдельные qml-файлы.
Может быть полезно для повторного использования небольших составных типов.

Component также можно создавать динамически с помощью Qt.createComponent().

Свойства:

*	progress : real - прогресс загрузки компонента, от 0.0 (ничего не загружено) до 1.0 (завершено).
*	status : enumeration - свойство сохраняет статус загрузки компонента.
	Статус может быть одним из следующих:
	*	Component.Null - нет данных для компонента
	*	Component.Ready - компонент загружен и может использоваться для создания экземпляров.
	*	Component.Loading - компонент загружается в настоящий момент
	*	Component.Error - ошибка при загрузке компонента.
		Вызов errorString () предоставит удобочитаемое описание любых ошибок.
*	url : url - URL-адрес, который использовался для создания компонента.

Сигналы:

*	completed() испускается после создания объекта.
	Его можно использовать для выполнения кода сценария при запуске, как только будет полностью
	создана среда QML.
	Соответствующий обработчик – это onCompleted.
	Он может быть объявлен на любом объекте.
	Порядок запуска обработчиков onCompleted не определен.
*	destruction() испускается, когда объект начинает уничтожаться.
	Его можно использовать для отмены работы, выполненной в обработчике сигнала completed()
	или другой императивный код в приложении.
	Соответствующий обработчик - onDestruction.
	Он может быть объявлен на любом объекте.
	Порядок работы обработчиков onDestruction не определен.

Метод createObject(QtObject parent, object properties) создает и возвращает экземпляр объекта
этого компонента, который будет иметь данный родительский элемент и свойства.
Аргумент properties необязателен.
Возвращает null, если создание объекта не выполняется.
Объект будет создан в том же контексте, что и тот, в котором был создан компонент.

Эта функция всегда возвращает null при вызове компонентов, которые не были созданы в QML.
Если вы хотите создать объект без установки родителя, укажите значение null для родительского значения.
Обратите внимание, что если возвращаемый объект должен отображаться, вы должны указать
действительное родительское значение или установить родительское свойство возвращаемого объекта,
иначе объект не будет виден.
Если родительский объект не предоставлен createObject(), ссылка на возвращенный объект должна быть
сохранена, чтобы он не был уничтожен сборщиком мусора

## Примеры Component

Обратите внимание, что, хотя прямоугольник сам по себе будет автоматически отображаться,
это не относится к указанному выше прямоугольнику, потому что он определен внутри Component.
Component инкапсулирует QML-типы внутри, как если бы они были определены в отдельном файле QML,
и не загружается до тех пор, пока не будет запрошен (в данном случае, двумя объектами Loader).
Поскольку Component не является производным от Item, вы не можете привязывать к нему что-либо.

## Свойства с параметром default

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

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

## Alias

Кроме определения свойств, которые хранят непосредственно какое-либо значение,
средства QML позволяют создавать alias (псевдо свойства), которые могут быть связаны
с другими существующими свойствами.
Операция чтения или записи такого свойства осуществляется как чтение или запись связанного
с ним свойства.
Синтаксис добавления alias похоже на объявление обычного свойства.
Так как псевдо свойство имеет тип аналогичный связанному свойству, явное указание типа заменено
на ключевое слово alias.
Вместо значения по умолчанию для alias необходимо обозначить свойство, на которое оно ссылается.
При этом нужно указать идентификатор объекта внутри компонента, а затем через точку его свойство.

Пример демонстрирует добавление alias buttonText для свойства text внутри элемента Text{}.

## Создание компонента

Элемент Component с вложенным объектом.
Объект Button является визуальным, но Component его скрывает.

Метод createComponent возвращает объект Component, созданный с использованием файла QML
по указанному URL-адресу, или null, если была указана пустая строка.

## Динамическое создание объектов

Динамическое создание объектов может осуществляться:

*	из компонента, определенного в этом же или другом qml-файле;
*	из строки QML, имеющей синтаксис qml-файла;
*	с помощью фактори паттерна в C++;
*	с помощью Loader - автоматического загрузчика;
*	из делегата представления.

## Loader — загрузчик динамических элементов

Loader используется для динамической загрузки компонентов QML.

Loader может загрузить файл QML (используя свойство source) или объект Component
(используя свойство sourceComponent).
Это полезно для задержки создания компонента до тех пор, пока он не понадобится:
например, когда компонент должен быть создан по требованию или когда компонент не должен создаваться
без необходимости по соображениям производительности.

Доступ к загруженному объекту возможен с помощью свойства item.
Если исходный или исходный компонент изменяется, любые ранее созданные объекты уничтожаются.
Установка source как пустой строки или установка sourceComponent как undefined уничтожает загруженный
объект, освобождая ресурсы и оставляя загрузчик пустым.

Если исходный компонент не является типом Item, Loader не применяет никаких специальных правил калибровки.
Когда Loader используется для загрузки визуальных типов, он применяет следующие правила калибровки:

Если размер не указан для загрузчика, загрузчик автоматически изменяется на размер загруженного
элемента после загрузки.

Если размер загрузчика указан явно, загруженный элемент будет изменен до размера загрузчика.

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

## Пример динамической загрузки

Пример динамической загрузки компонентов по разным нажатиям на элемент.

Свойство loader.source позволяет загрузить компонент по url.
Свойство loader.sourceComponent позволяет загрузить компонент, оппределённый в этом же файле. 
