Определение типов QML из C++
При расширении QML кодом C++, класс C++ может быть зарегистрирован в системе типов QML, чтобы позволить использовать этот класс как тип данных в коде QML. В то время как свойства, методы и сигналы любого класса, производного от QObject, доступны из QML, как обсуждается в Размещении атрибутов типов C++ в QML, такой класс нельзя использовать как тип данных из QML, пока он не будет зарегистрирован в системе типов. Кроме того, регистрация может предоставить другие функции, такие как возможность использования класса в качестве экземплярируемого типа QML объекта из QML или предоставление возможности импорта и использования одиночного экземпляра класса из QML.
Кроме того, модуль Qt QML предоставляет механизмы для реализации функций, специфичных для QML, таких как присоединённые свойства и свойства по умолчанию в C++.
(Обратите внимание, что ряд важных концепций, рассматриваемых в этом документе, показаны в учебном пособии Написание расширений QML с помощью C++.)
ПРИМЕЧАНИЕ: Все заголовки, объявляющие типы QML, должны быть доступны без каких-либо префиксов из пути включения проекта.
Регистрация типов C++ в системе типов QML
Класс, производный от QObject, может быть зарегистрирован в системе типов QML, чтобы позволить использовать этот тип как тип данных внутри кода QML.
Двигатель позволяет регистрировать как экземплярируемые, так и неэкземплярируемые типы. Регистрация экземплярируемого типа позволяет классу C++ использоваться в качестве определения типа объекта QML, позволяя использовать его в объявлениях объектов из кода QML для создания объектов этого типа. Регистрация также предоставляет двигателю дополнительные метаданные типа, позволяя использовать тип (и любые перечисления, объявленные классом) в качестве типа данных для значений свойств, параметров методов и возвращаемых значений, а также параметров сигналов, которые обмениваются между QML и C++.
Регистрация неэкземплярируемого типа также регистрирует класс как тип данных таким же образом, но тип не может быть использован для создания экземпляра в качестве типа QML объекта из QML. Это полезно, например, если тип имеет перечисления, которые должны быть доступны в QML, но сам тип не должен быть экземплярируемым.
Подробный справочник по выбору правильного подхода к представлению типов C++ в QML см. в Выбор правильного метода интеграции между C++ и QML.
Регистрация экземплярируемого типа объекта
Любой класс C++ производный от QObject может быть зарегистрирован как определение типа QML объекта. После регистрации класса в системе типов QML, класс может быть объявлен и экземпляризирован, как любой другой тип объекта из кода QML. После создания экземпляр класса может быть обработан из QML; как объясняется в Размещении атрибутов типов C++ в QML, свойства, методы и сигналы любого класса, производного от QObject, доступны из кода QML.
Для регистрации класса, производного от QObject, как экземплярируемого типа объекта QML, добавьте QML_ELEMENT или QML_NAMED_ELEMENT(<name>) в объявление класса и CONFIG += qmltypes, QML_IMPORT_NAME, и QML_IMPORT_MAJOR_VERSION в файл проекта. Это зарегистрирует класс в пространстве имён типов по заданной основной версии, используя либо имя класса, либо явно заданное имя в качестве имени типа QML. Незначительные версии будут получены из любых ревизий, прикреплённых к свойствам, методам или сигналам. Значение по умолчанию незначительной версии - 0. Вы можете явно ограничить доступность типа только определёнными незначительными версиями, добавив макрос QML_ADDED_IN_MINOR_VERSION() в объявление класса. Клиенты могут импортировать соответствующие версии пространства имён, чтобы использовать тип.
Например, предположим, что существует класс Message с свойствами author и creationDate.
class Message : public QObject
{
Q_OBJECT
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
QML_ELEMENT
public:
// ...
}; Этот тип может быть зарегистрирован путём добавления соответствующего пространства имён типа и номера версии в файл проекта. Например, чтобы сделать тип доступным в пространстве имён com.mycompany.messaging с версией 1.0:
CONFIG += qmltypes QML_IMPORT_NAME = com.mycompany.messaging QML_IMPORT_MAJOR_VERSION = 1
Если заголовок, в котором объявлен класс, недоступен из пути включения проекта, вам может потребоваться изменить путь включения, чтобы сгенерированный код регистрации мог быть скомпилирован:
INCLUDEPATH += com/mycompany/messaging
Тип может быть использован в объявлении объекта из QML, и к его свойствам можно читать и записывать, как показано в примере ниже:
import com.mycompany.messaging 1.0
Message {
author: "Amelie"
creationDate: new Date()
} Регистрация неэкземплярируемых типов
Иногда класс, производный от QObject, может потребоваться зарегистрировать в системе типов QML, но не как экземплярируемый тип. Например, это необходимо, если класс C++:
- является типом интерфейса, который не должен быть экземплярируемым
- является типом базового класса, который не нужно представлять в QML
- объявляет перечисление, которое должно быть доступно в QML, но иначе не должно быть экземплярируемым
- является типом, который должен быть предоставлен QML через одиночный экземпляр и не должен быть экземплярируемым из QML
Модуль Qt QML предоставляет несколько макросов для регистрации неэкземплярируемых типов:
- QML_ANONYMOUS регистрирует тип C++, который не может быть экземпляризован и не может быть упомянут из QML. Это позволяет двигателю приводить любой наследуемый тип, который является экземплярируемым из QML.
- QML_INTERFACE регистрирует существующий тип интерфейса Qt. Тип не может быть экземпляризован из QML, и вы не можете объявлять свойства QML с ним. Использование свойств C++ этого типа из QML выполнит ожидаемые преобразования интерфейса.
- QML_UNCREATABLE(причина) в сочетании с QML_ELEMENT или QML_NAMED_ELEMENT регистрирует именованный тип C++, который не может быть экземпляризован, но должен быть распознан как тип в системе типов QML. Это полезно, если перечисления или присоединённые свойства типа должны быть доступны из QML, но сам тип не должен быть экземпляризуемым. Параметр должен содержать сообщение об ошибке, которое будет выдано, если произойдёт попытка создания экземпляра типа.
- QML_SINGLETON в сочетании с QML_ELEMENT или QML_NAMED_ELEMENT регистрирует тип одиночного экземпляра, который может быть импортирован из QML, как обсуждается ниже.
Обратите внимание, что все типы C++, зарегистрированные в системе типов QML, должны быть производными от QObject, даже если они неэкземплярируемые.
Регистрация одиночных объектов с типом одиночного экземпляра
Тип одиночного экземпляра позволяет экспонировать свойства, сигналы и методы в пространстве имён без необходимости вручную создавать экземпляр объекта клиентом. QObject типы одиночного экземпляра, в частности, являются эффективным и удобным способом предоставления функциональности или значений глобальных свойств.
Обратите внимание, что типы одиночных экземпляров не имеют связанного QQmlContext, так как они используются во всех контекстах в движке. Экземпляры QObject типа одиночного экземпляра создаются и принадлежат QQmlEngine и будут уничтожены при уничтожении движка.
С типом одиночного экземпляра QObject можно взаимодействовать аналогично любому другому QObject или экземплярируемому типу, за исключением того, что будет существовать только один (созданный и принадлежащий движку) экземпляр, и к нему необходимо обращаться по имени типа, а не по идентификатору. Q_PROPERTY типов QObject одиночных экземпляров могут быть связаны, а функции Q_INVOKABLE API модуля QObject могут использоваться в выражениях обработчиков сигналов. Это делает типы одиночных экземпляров идеальным способом реализации стилей или тем, и они также могут быть использованы вместо импортов сценариев ".pragma library" для хранения глобального состояния или предоставления глобальной функциональности.
После регистрации тип одиночного экземпляра QObject может быть импортирован и использован, как любой другой экземпляр QObject, доступный в QML. Следующий пример предполагает, что тип одиночного экземпляра QObject был зарегистрирован в пространстве имён «MyThemeModule» с версией 1.0, где этот QObject имеет свойство QColor «color»:
import MyThemeModule 1.0 as Theme
Rectangle {
color: Theme.color // binding.
} Также может быть экспонирован QJSValue как тип одиночного экземпляра, однако клиенты должны понимать, что свойства такого типа одиночного экземпляра не могут быть связаны.
См. QML_SINGLETON для получения дополнительной информации о реализации и регистрации нового типа одиночного экземпляра и об использовании существующего типа одиночного экземпляра.
Примечание: Значения перечислений для зарегистрированных типов в QML должны начинаться с заглавной буквы.
Ревизии и версии типов
Многие функции регистрации типов требуют указания версий для зарегистрированного типа. Ревизии и версии типов позволяют создавать новые свойства или методы в новой версии, сохраняя обратную совместимость с предыдущими версиями.
Рассмотрим эти два файла QML:
// main.qml
import QtQuick 1.0
Item {
id: root
MyType {}
} // MyType.qml
import MyTypes 1.0
CppType {
value: root.x
} где CppType сопоставляется с классом C++ CppType.
Если автор CppType добавит свойство root в класс CppType в новой версии определения своего типа, root.x теперь будет соответствовать другому значению, потому что root также является id компонента верхнего уровня. Автор может указать, что новое свойство root доступно с определённой незначительной версии. Это позволяет добавлять новые свойства и функции к существующим типам без нарушения работы существующих программ.
Тег REVISION используется для обозначения свойства root как добавленного в ревизию 1 типа. Методы, такие как Q_INVOKABLE, сигналы и слоты также могут быть помечены для ревизии с помощью макроса Q_REVISION(x).
class CppType : public BaseType
{
Q_OBJECT
Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION 1)
QML_ELEMENT
signals:
Q_REVISION(1) void rootChanged();
}; Ревизии, указанные таким образом, автоматически интерпретируются как незначительные версии основной версии, заданной в файле проекта. В данном случае, root доступен только при импорте версии MyTypes 1.1 или выше. Импорты MyTypes версии 1.0 остаются неизменными.
По той же причине, новые типы, введенные в более поздних версиях, должны быть помечены макросом QML_ADDED_IN_MINOR_VERSION.
Эта функция языка позволяет вносить изменения в поведение без нарушения работы существующих приложений. Следовательно, авторы модулей QML всегда должны документировать, что изменилось между незначительными версиями, а пользователи модулей QML должны проверять, что их приложение по-прежнему работает правильно перед развертыванием обновлённого оператора импорта.
Ревизии базового класса, от которого зависит ваш тип, автоматически регистрируются при регистрации самого типа. Это полезно при наследовании от базовых классов, предоставляемых другими авторами, например, при расширении классов из модуля Qt Quick.
Примечание: Двигатель QML не поддерживает ревизии для свойств или сигналов объединенных и присоединенных объектов свойств.
Регистрация объектов расширения
При интеграции существующих классов и технологий в QML часто потребуется корректировка API, чтобы лучше вписаться в декларативную среду. Хотя лучшие результаты обычно достигаются путем непосредственного изменения исходных классов, если это невозможно или осложняется другими соображениями, объекты расширения позволяют ограниченные возможности расширения без непосредственных изменений.
Объекты расширения добавляют дополнительные свойства к существующему типу. Объекты расширения могут добавлять только свойства, а не сигналы или методы. Расширенное определение типа позволяет программисту предоставить дополнительный тип, известный как тип расширения, при регистрации класса. Свойства прозрачно объединяются с исходным целевым классом при использовании в QML. Например:
QLineEdit {
leftMargin: 20
} Свойство leftMargin является новым свойством, добавленным к существующему типу C++, QLineEdit, без изменения его исходного кода.
Макрос QML_EXTENDED(расширенный) предназначен для регистрации расширенных типов. Аргументом является имя другого класса, используемого в качестве расширения.
Вы также можете использовать QML_EXTENDED_NAMESPACE(пространство имен), чтобы зарегистрировать пространство имен, и особенно перечисления, объявленные внутри, как расширение типа.
Класс расширения является обычным QObject с конструктором, принимающим указатель на QObject. Однако создание класса расширения откладывается до первого доступа к расширенному свойству. Класс расширения создается, а целевой объект передается в качестве родителя. При доступе к свойству в оригинале используется соответствующее свойство в объекте расширения.
Пример объектов расширения демонстрирует использование объектов расширения.
Регистрация внешних типов
Возможно, существуют типы C++, которые нельзя изменить для хранения упомянутых выше макросов. Это могут быть типы из библиотек сторонних производителей или типы, которые должны удовлетворять некоторому контракту, противоречащему присутствию этих макросов. Тем не менее, вы все еще можете экспонировать эти типы в QML, используя макрос QML_FOREIGN. Для этого создайте отдельную структуру, состоящую только из макросов регистрации, как показано ниже:
// Contains class Immutable3rdParty
#include <3rdpartyheader.h>
struct Foreign
{
Q_GADGET
QML_FOREIGN(Immutable3rdParty)
QML_NAMED_ELEMENT(Accessible3rdParty)
QML_ADDED_IN_VERSION(2, 4)
// QML_EXTENDED, QML_SINGLETON ...
}; Из этого кода вы получаете тип QML с методами и свойствами Immutable3rdParty, а также QML-характеристики (например: одиночный, расширенный) указанные в Foreign.
Определение типов и атрибутов, специфичных для QML
Предоставление присоединенных свойств
В синтаксисе языка QML существует понятие присоединенных свойств и присоединенных обработчиков сигналов, которые являются дополнительными атрибутами, прикрепленными к объекту. По сути, такие атрибуты реализуются и предоставляются типом присоединения, и эти атрибуты могут быть прикреплены к объекту другого типа. Это контрастирует с обычными свойствами объектов, которые предоставляются самим типом объекта (или наследуемым типом объекта).
Например, элемент ниже использует присоединенные свойства и обработчики:
import QtQuick 2.0
Item {
width: 100; height: 100
focus: true
Keys.enabled: false
Keys.onReturnPressed: console.log("Return key was pressed")
} Здесь объект Item может получать доступ к значениям и устанавливать значения Keys.enabled и Keys.onReturnPressed. Это позволяет объекту Item получить доступ к этим дополнительным атрибутам как к расширению его собственных существующих атрибутов.
Шаги по реализации присоединенных объектов
При рассмотрении приведенного выше примера задействованы несколько сторон:
- Существует экземпляр анонимного типа присоединенного объекта с
enabledи сигналомreturnPressed, который был присоединен к объекту Item для предоставления доступа к этим атрибутам. - Объект Item является присоединяемым объектом, к которому был присоединен экземпляр типа присоединенного объекта.
- Keys является типом присоединения, который предоставляет присоединяемому объекту именованную квалификацию "Keys", через которую он может получить доступ к атрибутам присоединенного объекта.
При обработке этого кода движок QML создает один экземпляр типа присоединенного объекта и присоединяет этот экземпляр к объекту Item, тем самым предоставляя ему доступ к атрибутам enabled и returnPressed экземпляра.
Механизмы предоставления присоединенных объектов могут быть реализованы с помощью C++, путем предоставления классов для типа присоединенного объекта и типа присоединения. Для типа присоединенного объекта предоставьте класс, производный от QObject, который определяет атрибуты, которые должны быть доступны объектам присоединяемого объекта. Для типа присоединения предоставьте класс, производный от QObject, который:
- реализует статический метод qmlAttachedProperties() со следующей сигнатурой:
static <AttachedPropertiesType> *qmlAttachedProperties(QObject *object);
Этот метод должен возвращать экземпляр типа присоединенного объекта.
Двигатель QML вызывает этот метод, чтобы присоединить экземпляр типа присоединенного объекта к присоединяемому объекту, указанному параметром
object. Обычным, хотя и не обязательным, способом реализации этого метода является родительство возвращенного экземпляра вobject, чтобы предотвратить утечки памяти.Этот метод вызывается двигателем не более одного раза для каждого экземпляра объекта-присоединяемого, так как двигатель кэширует возвращаемый указатель на экземпляр для последующих обращений к присоединенному свойству. Следовательно, объект присоединения может быть удален только после уничтожения присоединяемого объекта
object. - объявляется как тип присоединения, добавив макрос QML_ATTACHED(присоединенный) к объявлению класса. Аргументом является имя типа присоединенного объекта
Реализация присоединенных объектов: пример
Например, рассмотрим тип Message , описанный в предыдущем примере:
class Message : public QObject
{
Q_OBJECT
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
QML_ELEMENT
public:
// ...
}; Предположим, необходимо сгенерировать сигнал на Message при публикации в форуме объявлений, а также отследить момент истечения срока действия сообщения на форуме. Поскольку добавление этих атрибутов непосредственно к Message не имеет смысла, так как атрибуты более релевантны контексту форума сообщений, их можно реализовать как присоединенные атрибуты к объекту Message , доступ к которым осуществляется через квалификатор "MessageBoard". С точки зрения ранее описанных концепций, здесь задействованы следующие стороны:
- Экземпляр анонимного типа присоединенного объекта, который предоставляет сигнал
publishedи свойство expired. Этот тип реализуется вMessageBoardAttachedTypeниже. - Объект
Message, который будет присоединяемым объектом - Тип
MessageBoard, который будет типом присоединения, используемым объектамиMessageдля доступа к присоединенным атрибутам
Вот пример реализации. Сначала нужен тип присоединенного объекта с необходимыми свойствами и сигналами, которые будут доступны присоединяемому объекту:
class MessageBoardAttachedType : public QObject
{
Q_OBJECT
Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged)
QML_ANONYMOUS
public:
MessageBoardAttachedType(QObject *parent);
bool expired() const;
void setExpired(bool expired);
signals:
void published();
void expiredChanged();
}; Затем тип присоединения, MessageBoard, должен объявить метод qmlAttachedProperties() , который возвращает экземпляр типа присоединенного объекта, как реализовано в MessageBoardAttachedType. Кроме того, MessageBoard должен быть объявлен как тип присоединения с помощью макроса QML_ATTACHED():
class MessageBoard : public QObject
{
Q_OBJECT
QML_ATTACHED(MessageBoardAttachedType)
QML_ELEMENT
public:
static MessageBoardAttachedType *qmlAttachedProperties(QObject *object)
{
return new MessageBoardAttachedType(object);
}
}; Теперь тип Message может получить доступ к свойствам и сигналам присоединенного типа:
Message {
author: "Amelie"
creationDate: new Date()
MessageBoard.expired: creationDate < new Date("January 01, 2015 10:45:00")
MessageBoard.onPublished: console.log("Message by", author, "has been
published!")
} Кроме того, реализация на C++ может получить доступ к экземпляру присоединенного объекта, который был присоединен к любому объекту, вызвав функцию qmlAttachedPropertiesObject().
Например:
Message *msg = someMessageInstance();
MessageBoardAttachedType *attached =
qobject_cast<MessageBoardAttachedType*>(qmlAttachedPropertiesObject<MessageBoard>(msg));
qDebug() << "Value of MessageBoard.expired:" << attached->expired(); Типы модификаторов свойств
Тип модификатора свойства — это особый вид типа QML-объекта. Экземпляр типа модификатора свойства влияет на свойство (экземпляра QML-объекта), к которому он применяется. Существует два типа типов модификаторов свойств:
- интерцепторы записи значения свойства
- источники значения свойства
Интерцептор записи значения свойства может использоваться для фильтрации или изменения значений при записи в свойства. В настоящее время единственный поддерживаемый интерцептор записи значения свойства — это тип Behavior, предоставляемый импортом QtQuick.
Источник значения свойства может использоваться для автоматического обновления значения свойства с течением времени. Клиенты могут определять свои собственные типы источников значения свойства. Различные типы анимации свойств, предоставляемые импортом QtQuick, являются примерами источников значения свойства.
Экземпляры типа модификатора свойства могут быть созданы и применены к свойству QML-объекта с помощью синтаксиса "<ТипМодификатора> on <ИмяСвойства>", как показано в следующем примере:
import QtQuick 2.0
Item {
width: 400
height: 50
Rectangle {
width: 50
height: 50
color: "red"
NumberAnimation on x {
from: 0
to: 350
loops: Animation.Infinite
duration: 2000
}
}
} Клиенты могут регистрировать свои собственные типы источников значения свойства, но в настоящее время не интерцепторы записи значения свойства.
Источники значения свойства
Источники значения свойства — это типы QML, которые могут автоматически обновлять значение свойства с течением времени, используя синтаксис <PropertyValueSource> on <property>. Например, различные типы анимации свойств, предоставляемые модулем QtQuick, являются примерами источников значения свойства.
Источник значения свойства может быть реализован на C++ путем наследования от QQmlPropertyValueSource и путем предоставления реализации, которая записывает различные значения в свойство с течением времени. Когда источник значения свойства применяется к свойству с использованием синтаксиса <PropertyValueSource> on <property> в QML, движок предоставляет ему ссылку на это свойство, чтобы значение свойства можно было обновить.
Например, предположим, что существует класс RandomNumberGenerator , который должен быть доступен в качестве источника значения свойства, чтобы при применении к свойству QML он обновлял значение свойства случайным числом каждые 500 миллисекунд. Кроме того, можно предоставить максимальное значение для этого генератора случайных чисел. Этот класс можно реализовать следующим образом:
class RandomNumberGenerator : public QObject, public QQmlPropertyValueSource
{
Q_OBJECT
Q_INTERFACES(QQmlPropertyValueSource)
Q_PROPERTY(int maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged);
QML_ELEMENT
public:
RandomNumberGenerator(QObject *parent)
: QObject(parent), m_maxValue(100)
{
QObject::connect(&m_timer, SIGNAL(timeout()), SLOT(updateProperty()));
m_timer.start(500);
}
int maxValue() const;
void setMaxValue(int maxValue);
virtual void setTarget(const QQmlProperty &prop) { m_targetProperty = prop; }
signals:
void maxValueChanged();
private slots:
void updateProperty() {
m_targetProperty.write(QRandomGenerator::global()->bounded(m_maxValue));
}
private:
QQmlProperty m_targetProperty;
QTimer m_timer;
int m_maxValue;
}; Когда движок QML сталкивается с использованием RandomNumberGenerator в качестве источника значения свойства, он вызывает RandomNumberGenerator::setTarget() для предоставления типу свойства, к которому было применено значение источника. Когда внутренний таймер в RandomNumberGenerator срабатывает каждые 500 миллисекунд, он записывает новое числовое значение в указанное свойство.
После регистрации класса RandomNumberGenerator в системе типов QML его можно использовать в QML в качестве источника значения свойства. Ниже он используется для изменения ширины Прямоугольника каждые 500 миллисекунд:
import QtQuick 2.0
Item {
width: 300; height: 300
Rectangle {
RandomNumberGenerator on width { maxValue: 300 }
height: 100
color: "red"
}
} Во всех остальных отношениях, источники значений свойств являются обычными типами QML, которые могут иметь свойства, сигналы, методы и т. д., но с дополнительной возможностью изменения значений свойств с использованием синтаксиса <PropertyValueSource> on <property>.
Когда объект-источник значения свойства назначается свойству, QML сначала пытается назначить его обычным способом, как если бы это был обычный тип QML. Только если это назначение не удаётся, движок вызывает метод setTarget(). Это позволяет использовать тип также и в контекстах, отличных от просто источника значения.
Указание свойств по умолчанию для типов QML-объектов
Любой тип, производный от QObject, зарегистрированный как порождаемый тип QML-объекта, может необязательно указать свойство по умолчанию для типа. Свойство по умолчанию — это свойство, которому автоматически назначаются дочерние элементы объекта, если они не назначены какому-либо конкретному свойству.
Свойство по умолчанию может быть установлено путём вызова макроса Q_CLASSINFO() для класса со значением "DefaultProperty". Например, класс MessageBoard ниже указывает своё свойство messages в качестве свойства по умолчанию для класса:
class MessageBoard : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
Q_CLASSINFO("DefaultProperty", "messages")
QML_ELEMENT
public:
QQmlListProperty<Message> messages();
private:
QList<Message *> m_messages;
}; Это позволяет дочерним элементам объекта MessageBoard автоматически назначаться его свойству messages , если они не назначены конкретному свойству. Например:
MessageBoard {
Message { author: "Naomi" }
Message { author: "Clancy" }
} Если messages не было установлено как свойство по умолчанию, то все объекты Message должны быть явно назначены свойству messages следующим образом:
MessageBoard {
messages: [
Message { author: "Naomi" },
Message { author: "Clancy" }
]
} (Кстати, свойство Item::data является свойством по умолчанию. Любые объекты Item, добавленные в это свойство data , также добавляются в список Item::children, поэтому использование свойства по умолчанию позволяет объявлять визуальные дочерние элементы для элемента без явного назначения их свойству children.)
Определение визуальных элементов с модулем Qt Quick
При создании пользовательских интерфейсов с модулем Qt Quick все QML-объекты, которые должны быть визуально отображены, должны быть производными от типа Item, так как это базовый тип для всех визуальных объектов в Qt Quick. Этот тип Item реализуется классом C++ QQuickItem, который предоставляется модулем Qt Quick. Поэтому этот класс должен быть унаследован, когда необходимо реализовать визуальный тип на C++, который можно интегрировать в пользовательский интерфейс на основе QML.
Дополнительную информацию см. в документации по QQuickItem. Кроме того, учебник Создание расширений QML с помощью C++ демонстрирует, как можно реализовать визуальный элемент на основе QQuickItem на C++ и интегрировать его в пользовательский интерфейс на основе Qt Quick.
Получение уведомлений об инициализации объекта
Для некоторых пользовательских типов QML-объектов может быть полезно отложить инициализацию определенных данных до тех пор, пока объект не будет создан и все его свойства не будут установлены. Например, это может быть необходимо, если инициализация является дорогостоящей, или если инициализация не должна выполняться до тех пор, пока все значения свойств не будут инициализированы.
Модуль Qt QML предоставляет QQmlParserStatus для наследования в этих целях. Он определяет ряд виртуальных методов, которые вызываются на различных этапах создания компонента. Для получения этих уведомлений класс C++ должен унаследовать QQmlParserStatus, а также уведомить систему Qt метаданных с помощью макроса Q_INTERFACES().
Например:
class MyQmlType : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
QML_ELEMENT
public:
virtual void componentComplete()
{
// Perform some initialization here now that the object is fully created
}
};
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qtqml-cppintegration-definetypes.html