Определение типов QML из C++
При расширении QML кодом на C++, класс C++ может быть зарегистрирован в системе типов QML, что позволит использовать класс как тип данных в коде QML. Хотя свойства, методы и сигналы любого класса, производного от QObject, доступны из QML, как обсуждается в Размещении атрибутов типов C++ в QML, такой класс нельзя использовать в качестве типа данных из QML, пока он не будет зарегистрирован в системе типов. Кроме того, регистрация может обеспечить другие возможности, такие как возможность использования класса в качестве экземпляризуемого типа QML-объекта из QML или включение в QML импорта и использования одиночного экземпляра класса.
Кроме того, модуль Qt QML предоставляет механизмы для реализации QML-специфических функций, таких как прикреплённые свойства и свойства по умолчанию в C++.
(Обратите внимание, что ряд важных концепций, рассматриваемых в этом документе, продемонстрированы в учебном пособии по написанию расширений QML с помощью C++).
Регистрация типов C++ в системе типов QML
Класс, производный от QObject, может быть зарегистрирован в системе типов QML для возможности использования типа в качестве типа данных из кода QML.
Двигатель позволяет регистрировать как экземпляризуемые, так и неэкземпляризуемые типы. Регистрация экземпляризуемого типа позволяет использовать класс C++ в качестве определения типа QML-объекта, что позволяет использовать его в объявлениях объектов из кода QML для создания объектов этого типа. Регистрация также предоставляет движку дополнительные метаданные типа, позволяя использовать тип (и любые перечисления, объявленные классом) в качестве типа данных для значений свойств, параметров методов и возвращаемых значений, а также параметров сигналов, которые обмениваются между QML и C++.
Регистрация неэкземпляризуемого типа также регистрирует класс как тип данных таким образом, но тип не может быть использован для создания QML-объекта из QML. Это полезно, например, если тип содержит перечисления, которые должны быть доступны в QML, но сам тип не должен быть экземпляризуемым.
Регистрация экземпляризуемого типа объекта
Любой класс C++, производный от QObject, может быть зарегистрирован в качестве определения QML-типа объекта. После регистрации класса в системе типов QML класс можно объявлять и экземпляризировать как любой другой тип объекта из кода QML. После создания экземпляр класса может быть обработан из QML; как объясняется в Размещении атрибутов типов C++ в QML, свойства, методы и сигналы любого класса, производного от QObject, доступны из кода QML.
Для регистрации класса, производного от QObject, в качестве экземпляризуемого QML-типа объекта, вызовите qmlRegisterType() для регистрации класса в качестве QML-типа в определенном пространстве имён типов. Клиенты могут затем импортировать это пространство имён для использования типа.
Например, предположим, что существует класс 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)
public:
// ...
}; Этот тип может быть зарегистрирован путём вызова qmlRegisterType() с соответствующим пространством имён типов и номером версии. Например, чтобы сделать тип доступным в пространстве имён com.mycompany.messaging с версией 1.0:
qmlRegisterType<Message>("com.mycompany.messaging", 1, 0, "Message"); Тип может быть использован в объявлении объекта из QML, и его свойства могут читаться и записываться, как показано в примере ниже:
import com.mycompany.messaging 1.0
Message {
author: "Amelie"
creationDate: new Date()
} Регистрация неэкземпляризуемых типов
Иногда класс, производный от QObject, может потребоваться зарегистрировать в системе типов QML, но не в качестве экземпляризуемого типа. Например, это происходит, если класс C++:
- является типом интерфейса, который не должен быть экземпляризуемым
- является типом базового класса, который не нужно экспонировать в QML
- объявляет перечисления, которые должны быть доступны в QML, но в противном случае не должны быть экземпляризуемыми
- является типом, который должен быть предоставлен QML через экземпляр singleton, и не должен быть экземпляризуем из QML
Модуль Qt QML предоставляет несколько методов для регистрации неэкземпляризуемых типов:
- qmlRegisterType() (без параметров) регистрирует тип C++, который не является экземпляризуемым и не может быть сослаться из QML. Это позволяет двигателю принудительно привести к типу любые наследуемые типы, которые могут быть экземпляризованы из QML.
- qmlRegisterInterface() регистрирует тип интерфейса Qt с указанным именем типа QML. Тип не может быть экземпляризован из QML, но может быть сохранён по его имени типа.
- qmlRegisterUncreatableType() регистрирует именованный тип C++, который не может быть экземпляризован, но должен быть идентифицируемым типом для системы типов QML. Это полезно, если перечисления или прикреплённые свойства типа должны быть доступны из QML, но сам тип не должен быть экземпляризуемым.
- qmlRegisterSingletonType() регистрирует тип singleton, который может быть импортирован из QML, как обсуждалось ниже.
Обратите внимание, что все типы C++, зарегистрированные в системе типов QML, должны быть производными от QObject, даже если они неэкземпляризуемы.
Регистрация объектов singleton с типом singleton
Тип singleton позволяет экспонировать свойства, сигналы и методы в пространстве имён без необходимости для клиента вручную создавать экземпляр объекта. QObject типы singleton, в частности, представляют собой эффективный и удобный способ предоставления функциональности или глобальных значений свойств.
Обратите внимание, что типы singleton не имеют связанного QQmlContext, так как они совместно используются во всех контекстах в двигателе. Экземпляры QObject типов singleton создаются и принадлежат QQmlEngine, и будут уничтожены при уничтожении двигателя.
С QObject типом singleton можно взаимодействовать аналогичным образом, как с любым другим QObject или экземпляризуемым типом, за исключением того, что будет существовать только один (созданный и принадлежащий двигателю) экземпляр, и он должен быть сохранён по имени типа, а не по идентификатору. Q_PROPERTY QObject типов singleton могут быть связаны с, и Q_INVOKABLE функции API модуля QObject могут быть использованы в выражениях обработчиков сигналов. Это делает типы singleton идеальным способом реализации стилей или тем, а также их можно использовать вместо импортов скриптов ".pragma library" для хранения глобального состояния или предоставления глобальной функциональности.
После регистрации QObject типа singleton может быть импортирован и использован как любой другой экземпляр QObject, экспонированный в QML. Следующий пример предполагает, что QObject тип singleton был зарегистрирован в пространстве имён "MyThemeModule" с версией 1.0, где у этого QObject есть Q_PROPERTY "color" типа QColor:
import MyThemeModule 1.0 as Theme
Rectangle {
color: Theme.color // binding.
} QJSValue также может быть экспонирован как тип singleton, однако клиенты должны понимать, что свойства такого типа singleton не могут быть связаны.
См. qmlRegisterSingletonType() для получения дополнительной информации о реализации и регистрации нового типа singleton и о использовании существующего типа 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)
signals:
Q_REVISION(1) void rootChanged();
}; Для регистрации новой ревизии класса в определённой версии используется следующая функция:
template<typename T, int metaObjectRevision> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
Для регистрации CppType версии 1 для MyTypes 1.1:
qmlRegisterType<CppType,1>("MyTypes", 1, 1, "CppType") root доступен только при импорте MyTypes версии 1.1.
По той же причине, новые типы, введённые в более поздних версиях, должны использовать аргумент номер версии в qmlRegisterType.
Эта функция языка позволяет вносить изменения в поведение без нарушения работы существующих приложений. Поэтому авторы модулей QML должны всегда документировать, что изменилось между версиями, а пользователи модулей QML должны убедиться, что их приложение всё ещё работает корректно перед развертыванием обновлённого оператора импорта.
Вы также можете зарегистрировать ревизию базового класса, от которого зависит ваш тип, используя функцию qmlRegisterRevision():
template<typename T, int metaObjectRevision> int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) template<typename T, int metaObjectRevision> int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
Например, если BaseType был изменён и теперь имеет ревизию 1, вы можете указать, что ваш тип использует новую ревизию:
qmlRegisterRevision<BaseType,1>("MyTypes", 1, 1); Это полезно при наследовании от базовых классов, предоставленных другими авторами, например, при расширении классов из модуля Qt Quick.
Регистрация объектов расширений
При интеграции существующих классов и технологий в QML, API часто необходимо дорабатывать, чтобы лучше вписаться в декларативную среду. Хотя лучшие результаты обычно достигаются путём непосредственного изменения исходных классов, если это невозможно или усложняется другими проблемами, объекты расширений позволяют ограничить возможности расширения без непосредственных модификаций.
Объекты расширения добавляют дополнительные свойства к существующему типу. Объекты расширения могут добавлять только свойства, а не сигналы или методы. Расширенное определение типа позволяет программисту предоставить дополнительный тип, известный как тип расширения, при регистрации класса. Свойства прозрачно объединяются с исходным целевым классом при использовании из QML. Например:
QLineEdit {
leftMargin: 20
} Свойство leftMargin — это новое свойство, добавленное к существующему типу C++, QLineEdit, без изменения его исходного кода.
Функция qmlRegisterExtendedType() предназначена для регистрации расширенных типов. Обратите внимание, что она имеет две формы.
template<typename T, typename ExtendedT> int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) template<typename T, typename ExtendedT> int qmlRegisterExtendedType()
Эти функции следует использовать вместо обычных qmlRegisterType() вариантов. Аргументы идентичны соответствующим функциям регистрации без расширения, за исключением параметра ExtendedT, который представляет тип объекта расширения.
Класс расширения — это обычный QObject с конструктором, принимающим указатель на QObject. Однако создание класса расширения откладывается до первого обращения к расширенному свойству. Класс расширения создается, а целевой объект передается в качестве родительского объекта. При обращении к свойству исходного объекта вместо него используется соответствующее свойство объекта расширения.
Пример объектов расширения демонстрирует использование объектов расширения.
Определение типов и атрибутов, специфичных для QML
Предоставление прикреплённых объектов для аннотаций данных
В синтаксисе языка QML существует понятие прикреплённых свойств и прикреплённых обработчиков сигналов, которые являются дополнительными атрибутами, прикреплёнными к объекту. По существу, такие атрибуты реализуются и предоставляются типом прикрепления, и эти атрибуты могут быть прикреплены к объекту другого типа. Это контрастирует с обычными свойствами объекта, которые предоставляются самим типом объекта (или типом, унаследованным от объекта).
Например, нижеприведенный Item использует прикрепленные свойства и прикрепленные обработчики:
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_DECLARE_TYPEINFO() с флагом QML_HAS_ATTACHED_PROPERTIES
Реализация прикреплённых объектов: пример
Например, рассмотрим тип 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)
public:
// ...
}; Предположим, необходимо инициировать сигнал на Message, когда он публикуется на доске объявлений, а также отслеживать, когда сообщение истекло на доске объявлений. Поскольку добавление этих атрибутов непосредственно к Message не имеет смысла, так как эти атрибуты более актуальны в контексте доски объявлений, их можно реализовать как прикреплённые атрибуты к объекту Message, которые предоставляются с помощью квалификатора "MessageBoard". В терминах ранее описанных концепций участвующие стороны здесь таковы:
- Экземпляр анонимного типа прикреплённого объекта, который предоставляет сигнал
publishedи свойство expired. Этот тип реализован вMessageBoardAttachedTypeниже - Объект
Message, который будет объектом, к которому прикреплен - Тип
MessageBoard, который будет типом прикрепления, используемым объектамиMessageдля доступа к прикреплённым атрибутам
Ниже приведен пример реализации. Сначала нужен тип прикреплённого объекта с необходимыми свойствами и сигналами, которые будут доступны объекту, к которому прикреплен:
class MessageBoardAttachedType : public QObject
{
Q_OBJECT
Q_PROPERTY(bool expired READ expired WRITE expired NOTIFY expiredChanged)
public:
MessageBoardAttachedType(QObject *parent);
bool expired() const;
void setExpired(bool expired);
signals:
void published();
void expiredChanged();
}; Затем тип прикрепления, MessageBoard, должен объявить метод qmlAttachedProperties(), который возвращает экземпляр типа прикреплённого объекта, как реализован в MessageBoardAttachedType. Кроме того, Message board должен быть объявлен как тип прикрепления с помощью макроса QML_DECLARE_TYPEINFO():
class MessageBoard : public QObject
{
Q_OBJECT
public:
static MessageBoard *qmlAttachedProperties(QObject *object)
{
return new MessageBoardAttachedType(object);
}
};
QML_DECLARE_TYPEINFO(MessageBoard, QML_HAS_ATTACHED_PROPERTIES) Теперь тип 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-объекта с помощью синтаксиса «<ТипМодификатора> по <ИмяСвойства>», как показано в следующем примере:
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);
public:
RandomNumberGenerator(QObject *parent)
: QObject(parent), m_maxValue(100)
{
qsrand(QDateTime::currentDateTime().toTime_t());
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(qrand() % m_maxValue);
}
private:
QQmlProperty m_targetProperty;
QTimer m_timer;
int m_maxValue;
}; При обнаружении движком QML использования RandomNumberGenerator в качестве источника значения свойства он вызывает RandomNumberGenerator::setTarget() для обеспечения типа свойством, к которому было применено значение источника. Когда внутренний таймер в RandomNumberGenerator срабатывает каждые 500 миллисекунд, он записывает новое числовое значение в это указанное свойство.
После регистрации класса RandomNumberGenerator в системе типов QML его можно использовать в QML в качестве источника значения свойства. Ниже он используется для изменения ширины Rectangle каждые 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")
public:
QQmlListProperty<Message> messages() const;
private:
QList<Message *> 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)
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/archives/qt-5.6/qtqml-cppintegration-definetypes.html