1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
4\page qtqml-cppintegration-definetypes.html
5\title Defining QML Types from C++
6\brief Description of ways to define QML object types from C++ code
8When extending QML with C++ code, a C++ class can be registered with the QML
9type system to enable the class to be used as a data type within QML code.
10While the properties, methods and signals of any QObject-derived class are
11accessible from QML, as discussed in \l{qtqml-cppintegration-exposecppattributes.html}
12{Exposing Attributes of C++ Types to QML}, such a class cannot be used as a
13data type from QML until it is registered with the type system. Additionally
14registration can provide other features, such as allowing a class to be used
15as an instantiable \l{qtqml-typesystem-objecttypes.html}{QML object type} from
16QML, or enabling a singleton instance of the class to be imported and used
19Additionally, the \l {Qt QML} module provides mechanisms for implementing QML-specific
20features such as \e{attached properties} and \e{default properties} in C++.
22(Note that a number of the important concepts covered in this document are
23demonstrated in the \l{Writing QML Extensions with C++} tutorial.)
25\b{NOTE:} All headers that declare QML types need to be accessible without any prefix from the project's include path.
27For more information about C++ and the different QML integration methods,
29\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page.
31\section1 Registering C++ Types with the QML Type System
33A QObject-derived class can be registered with the QML type system to enable the
34type to be used as a data type from within QML code.
36The engine allows the registration of both instantiable and non-instantiable
37types. Registering an instantiable type enables a C++ class to be used as the
38definition of a QML object type, allowing it to be used in object declarations
39from QML code to create objects of this type. Registration also provides
40the engine with additional type metadata, enabling the type (and any enums
41declared by the class) to be used as a data type for property values, method
42parameters and return values, and signal parameters that are exchanged between
45Registering a non-instantiable type also registers the class as a data type in
46this manner, but the type cannot be used instantiated as a QML object type
47from QML. This is useful, for example, if a type has enums that should be
48exposed to QML but the type itself should not be instantiable.
50For a quick guide to choosing the correct approach to expose C++ types to QML,
51see \l {Choosing the Correct Integration Method Between C++ and QML}.
53\section2 Preconditions
55All the macros mentioned below are available from the \c qqmlregistration.h
56header. You need to add the following code to the files using them in order to
57make the macros available:
60#include <QtQml/qqmlregistration.h>
63Furthermore, your class declarations have to live in headers reachable via your
64project's include path. The declarations are used to generate registration code
65at compile time, and the registration code needs to include the headers that
66contain the declarations.
68\section2 Registering an Instantiable Object Type
70\b{Any QObject-derived C++ class can be registered as the definition of a
71\l{qtqml-typesystem-objecttypes.html}{QML object type}}. Once a
72class is registered with the QML type system, the class can be declared and
73instantiated like any other object type from QML code. Once created, a
74class instance can be manipulated from QML; as
75\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
76Types to QML} explains, the properties, methods and signals of any
77QObject-derived class are accessible from QML code.
79To register a QObject-derived class as an instantiable QML object type, add
80\c QML_ELEMENT or \c QML_NAMED_ELEMENT(<name>) to the class declaration. You
81also need to make adjustments in the build system. For qmake, add
82\c {CONFIG += qmltypes}, a \c {QML_IMPORT_NAME}, and a
83\c QML_IMPORT_MAJOR_VERSION to your project file. For CMake, the file containing
84the class should be part of a target set-up with
85\l{qt_add_qml_module}{qt_add_qml_module()}.
86This will register the class into the type namespace under the given major version,
87using either the class name or an explicitly given name as QML type name. The
88minor version(s) will be derived from any revisions attached to properties,
89methods, or signals. The default minor version is \c 0. You can explicitly
90restrict the type to be available only from specific minor versions by adding
91the \c QML_ADDED_IN_MINOR_VERSION() macro to the class declaration. Clients can
92import suitable versions of the namespace in order to use the type.
94For example, suppose there is a \c Message class with \c author and
95\c creationDate properties:
98class Message : public QObject
101 Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
102 Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
109This type can be registered by adding an appropriate type namespace and version
110number to the project file. For example, to make the type available in the
111\c com.mycompany.messaging namespace with version 1.0:
113\if defined(onlinedocs)
114 \tab {build-qt-app}{tab-cmake}{CMake}{selected}
115 \tab {build-qt-app}{tab-qmake}{qmake}{}
116 \tabcontent {tab-cmake}
118 \section3 Using CMake
121 qt_add_qml_module(messaging
122 URI com.mycompany.messaging
125 message.cpp message.h
128\if defined(onlinedocs)
130 \tabcontent {tab-qmake}
132 \section3 Using QMake
136 QML_IMPORT_NAME = com.mycompany.messaging
137 QML_IMPORT_MAJOR_VERSION = 1
140 If the header the class is declared in is not accessible from your project's
141 include path, you may have to amend the include path so that the generated
142 registration code can be compiled.
145 INCLUDEPATH += com/mycompany/messaging
147\if defined(onlinedocs)
153The type can be used in an \l{qtqml-syntax-basics.html#object-declarations}
154{object declaration} from QML, and its properties can be read and written to,
155as per the example below:
158import com.mycompany.messaging
162 creationDate: new Date()
166\section2 Registering Value Types
168Any type with a \l{Q_GADGET} macro can the registered as a
169\l{qtqml-typesystem-valuetypes.html}{QML value type}}. Once such a type is
170registered with the QML type system it can be used as property type in QML
171code. Such an instance can be manipulated from QML; as
172\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
173Types to QML} explains, the properties and methods of any value type are
174accessible from QML code.
176In contrast to object types, value types require \b{lower case} names. The
177preferred way to register them is using the \l{QML_VALUE_TYPE} or
178\l{QML_ANONYMOUS} macros. There is no equivalent to \l{QML_ELEMENT} as your
179C++ classes are typically going to have upper case names. Otherwise the
180registration is very similar to the registration of object types.
182For example, suppose you want to register a value type \c{person} that consists
183of two strings for first and last name:
189 Q_PROPERTY(QString firstName READ firstName WRITE setFirstName)
190 Q_PROPERTY(QString lastName READ lastName WRITE setLastName)
191 QML_VALUE_TYPE(person)
197There are some further limitations on what you can do with value types:
199\li Value types cannot be singletons.
200\li Value types need to be default-constructible and copy-constructible.
201\li Using QProperty as a member of a value type is problematic. Value types get
202 copied, and you would need to decide what to do with any bindings on the
203 QProperty at that point. You should not use QProperty in value types.
204\li Value types cannot provide attached properties.
205\li The API to define extensions to value types (\l{QML_EXTENDED}) is not public
206 and subject to future changes.
209\section2 Registering Non-Instantiable Types
211Sometimes a QObject-derived class may need to be registered with the QML type
212system but not as an instantiable type. For example, this is the case if a C++
216\li is an interface type that should not be instantiable
217\li is a base class type that does not need to be exposed to QML
218\li declares some enum that should be accessible from QML, but otherwise should
220\li is a type that should be provided to QML through a singleton instance, and
221should not be instantiable from QML
224The \l {Qt QML} module provides several macros for registering non-instantiable
228\li QML_ANONYMOUS registers a C++ type that is not instantiable and cannot be
229referred to from QML. This enables the engine to coerce any inherited types that
230are instantiable from QML.
231\li QML_INTERFACE registers an existing Qt interface type. The type is
232not instantiable from QML, and you cannot declare QML properties with it. Using
233C++ properties of this type from QML will do the expected interface casts,
235\li QML_UNCREATABLE(reason) combined with with QML_ELEMENT or QML_NAMED_ELEMENT
236registers a named C++ type that is not instantiable but should be identifiable
237as a type to the QML type system. This is useful if a type's enums or attached
238properties should be accessible from QML but the type itself should not be
239instantiable. The parameter should be an error message to be emitted if an
240attempt at creating an instance of the type is detected.
241\li QML_SINGLETON combined with QML_ELEMENT or QML_NAMED_ELEMENT registers a
242singleton type that can be imported from QML, as discussed below.
245Note that all C++ types registered with the QML type system must be
246QObject-derived, even if they are non-instantiable.
249\section3 Registering Singleton Objects with a Singleton Type
251A singleton type enables properties, signals and methods to be exposed in
252a namespace without requiring the client to manually instantiate an
253object instance. QObject singleton types in particular are an efficient and
254convenient way to provide functionality or global property values.
256Note that singleton types do not have an associated QQmlContext as they are
257shared across all contexts in an engine. QObject singleton type instances
258are constructed and owned by the QQmlEngine, and will be destroyed when
259the engine is destroyed.
261A QObject singleton type can be interacted with in a manner similar to any
262other QObject or instantiated type, except that only one (engine constructed
263and owned) instance will exist, and it must be referenced by type name rather
264than id. Q_PROPERTYs of QObject singleton types may be bound to, and Q_INVOKABLE
265functions of QObject module APIs may be used in signal handler expressions.
266This makes singleton types an ideal way to implement styling or theming, and
267they can also be used instead of ".pragma library" script imports to store global
268state or to provide global functionality.
270Once registered, a QObject singleton type may be imported and used like any
271other QObject instance exposed to QML. The following example assumes that
272a QObject singleton type was registered into the "MyThemeModule" namespace
273with version 1.0, where that QObject has a QColor "color" Q_PROPERTY:
276import MyThemeModule 1.0 as Theme
279 color: Theme.color // binding.
283A QJSValue may also be exposed as a singleton type, however clients should
284be aware that properties of such a singleton type cannot be bound to.
286See \l{QML_SINGLETON} for more information on how implement and
287register a new singleton type, and how to use an existing singleton type.
289\note Enum values for registered types in QML should start with a capital.
291\section2 Final properties
293Properties declared final using the \c FINAL modifier to \l Q_PROPERTY cannot
294be overridden. This means that any properties or functions of the same name,
295declared either in QML or in C++ on derived types, are ignored by the QML
296engine. You should declare properties \c FINAL when possible, in order to avoid
297accidental overrides. An override of a property is visible not only in
298derived classes, but also to QML code executing the context of the base class.
299Such QML code, typically expects the original property, though. This is a
300frequent source of mistakes.
302Properties declared \c FINAL can also not be overridden by functions in QML, or
303by \l Q_INVOKABLE methods in C++.
305\section2 Type Revisions and Versions
307Many of the type registration functions require versions to be specified
308for the registered type. Type revisions and versions allow new properties
309or methods to exist in the new version while remaining compatible with
312Consider these two QML files:
332where \c CppType maps to the C++ class \c CppType.
334If the author of CppType adds a \c root property to CppType in a new
335version of their type definition, \c root.x now resolves to a different value
336because \c root is also the \c id of the top level component. The author could
337specify that the new \c root property is available from a specific minor
338version. This permits new properties and features to be added to existing
339types without breaking existing programs.
341The REVISION tag is used to mark the \c root property as added in revision 1
342of the type. Methods such as Q_INVOKABLE's, signals and slots can also be
343tagged for a revision using the \c Q_REVISION(x) macro:
346class CppType : public BaseType
349 Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION 1)
353 Q_REVISION(1) void rootChanged();
357The revisions given this way are automatically interpreted as minor versions to
358the major version given in the project file. In this case, \c root is only
359available when \c MyTypes version 1.1 or higher is imported. Imports of
360\c MyTypes version 1.0 remain unaffected.
362For the same reason, new types introduced in later versions should be tagged
363with the QML_ADDED_IN_MINOR_VERSION macro.
365This feature of the language allows for behavioural changes to be made
366without breaking existing applications. Consequently QML module authors
367should always remember to document what changed between minor versions, and
368QML module users should check that their application still runs correctly
369before deploying an updated import statement.
371Revisions of a base class that your type depends upon are automatically
372registered when registering the type itself. This is useful when deriving
373from base classes provided by other authors, e.g. when extending classes from
376\note The QML engine does not support revisions for properties or signals of
377grouped and attached property objects.
379\section2 Registering Extension Objects
381When integrating existing classes and technology into QML, APIs will
382often need tweaking to fit better into the declarative environment.
383Although the best results are usually obtained by modifying the original
384classes directly, if this is either not possible or is complicated by some
385other concerns, extension objects allow limited extension possibilities
386without direct modifications.
388\e{Extension objects} add additional properties to an existing type. An extended
389type definition allows the programmer to supply an additional type, known as the
390\e{extension type}, when registering the class. Its members are transparently
391merged with the original target class when used from within QML. For example:
399The \c leftMargin property is a new property added to an existing C++ type, \l
400QLineEdit, without modifying its source code.
402The QML_EXTENDED(extension) macro is for registering extended types. The
403argument is the name of another class to be used as extension.
405You can also use QML_EXTENDED_NAMESPACE(namespace) to register a namespace, and
406especially the enumerations declared within, as an extension to a type. If the
407type you are extending is itself a namespace, you need to use
408QML_NAMESPACE_EXTENDED(namespace) instead.
410An extension class is a regular QObject, with a constructor that takes a QObject
411pointer. However, the extension class creation is delayed until the first
412extended property is accessed. The extension class is created and the target
413object is passed in as the parent. When the property on the original is
414accessed, the corresponding property on the extension object is used instead.
416\section2 Registering Foreign Types
418There may be C++ types that cannot be modified to hold the above mentioned
419macros. Those may be types from 3rdparty libraries, or types that need to
420fulfill some contract that contradicts the presence of those macros. You can
421still expose those types to QML, though, using the QML_FOREIGN macro. In order
422to do this, create a separate struct that consists entirely of the registration
426// Contains class Immutable3rdParty
427#include <3rdpartyheader.h>
432 QML_FOREIGN(Immutable3rdParty)
433 QML_NAMED_ELEMENT(Accessible3rdParty)
434 QML_ADDED_IN_VERSION(2, 4)
435 // QML_EXTENDED, QML_SINGLETON ...
439From this code, you get a QML type with the methods and properties of
440Immutable3rdParty, and the QML traits (e.g.: singleton, extended) specified in
443\section1 Defining QML-Specific Types and Attributes
445\section2 Providing Attached Properties
446\keyword Integrating QML and C++ - Attached Properties
448In the QML language syntax, there is a notion of \l{Attached properties and
449attached signal handlers}{\e {attached properties} and \e {attached signal
450handlers}}, which are additional attributes that are attached to an object.
451Essentially, such attributes are implemented and provided by an \e {attaching
452type}, and these attributes may be \e attached to an object of another type.
453This contrasts with ordinary object properties which are provided by the object
454type itself (or the object's inherited type).
456For example, the \l Item below uses attached properties and attached handlers:
462 width: 100; height: 100
466 Keys.onReturnPressed: console.log("Return key was pressed")
470Here, the \l Item object is able to access and set the values of \c Keys.enabled
471and \c Keys.onReturnPressed. This allows the \l Item object to access these
472extra attributes as an extension to its own existing attributes.
474\section3 Steps for Implementing Attached Objects
476When considering the above example, there are several parties involved:
479\li There is an instance of an anonymous \e {attached object type}, with
480an \c enabled and a \c returnPressed signal, that has been attached to the
481\l Item object to enable it to access and set these attributes.
482\li The \l Item object is the \e {attachee}, to which the instance of the \e
483{attached object type} has been attached.
484\li \l Keys is the \e {attaching type}, which provides the \e {attachee} with a
485named qualifier, "Keys", through which it may access the attributes of the
486\e {attached object type}.
489When the QML engine processes this code, it creates a single instance of the
490\e {attached object type} and attaches this instance to the \l Item object,
491thereby providing it with access to the \c enabled and \c returnPressed
492attributes of the instance.
494The mechanisms for providing attached objects can be implemented from C++ by
495providing classes for the \e {attached object type} and \e {attaching type}.
496For the \e{attached object type}, provide a QObject-derived class that defines
497the attributes to be made accessible to \e attachee objects. For the
498\e {attaching type}, provide a QObject-derived class that:
501\li implements a static qmlAttachedProperties() with the following signature:
503 static <AttachedPropertiesType> *qmlAttachedProperties(QObject *object);
506 This method should return an instance of the \e{attached object type}.
508 The QML engine invokes this method in order to attach an instance of
509 the attached object type to the \e attachee specified by the \c object
510 parameter. It is customary, though not strictly required, for this method
511 implementation to parent the returned instance to \c object in order
512 to prevent memory leaks.
514 This method is called at most once by the engine for each attachee object
515 instance, as the engine caches the returned instance pointer for subsequent
516 attached property accesses. Consequently the attachment object may not be
517 deleted until the attachee \c object is destroyed.
519\li is declared as an attaching type, by adding the QML_ATTACHED(attached) macro
520 to the class declaration. The argument is the name of the
521 \e{attached object type}
525\section3 Implementing Attached Objects: An Example
527For example, take the \c Message type described in an \l{Registering an
528Instantiable Object Type}{earlier example}:
531class Message : public QObject
534 Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
535 Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
542Suppose it is necessary to trigger a signal on a \c Message when it is
543published to a message board, and also track when the message has expired on
544the message board. Since it doesn't make sense to add these attributes
545directly to a \c Message, as the attributes are more relevant to the message
546board context, they could be implemented as \e attached attributes on a
547\c Message object that are provided through a "MessageBoard" qualifier. In
548terms of the concepts described earlier, the parties involved here are:
551\li An instance of an anonymous \e{attached object type}, which provides a
552 \c published signal and an expired property. This type is implemented by
553 \c MessageBoardAttachedType below
554\li A \c Message object, which will be the \e attachee
555\li The \c MessageBoard type, which will be the \e {attaching type} that is
556 used by \c Message objects to access the attached attributes
559Following is an example implementation. First, there needs to be an
560\e {attached object type} with the necessary properties and signals that
561will be accessible to the \e attachee:
564class MessageBoardAttachedType : public QObject
567 Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged)
570 MessageBoardAttachedType(QObject *parent);
571 bool expired() const;
572 void setExpired(bool expired);
575 void expiredChanged();
579Then the \e {attaching type}, \c MessageBoard, must declare a \c
580qmlAttachedProperties() method that returns an instance of the
581\e {attached object type} as implemented by MessageBoardAttachedType.
582Additionally, \c MessageBoard must be declared as an attaching type
583via the QML_ATTACHED() macro:
586class MessageBoard : public QObject
589 QML_ATTACHED(MessageBoardAttachedType)
592 static MessageBoardAttachedType *qmlAttachedProperties(QObject *object)
594 return new MessageBoardAttachedType(object);
599Now, a \c Message type can access the properties and signals of the attached
605 creationDate: new Date()
607 MessageBoard.expired: creationDate < new Date("January 01, 2015 10:45:00")
608 MessageBoard.onPublished: console.log("Message by", author, "has been
613Additionally, the C++ implementation may access the attached object instance
614that has been attached to any object by calling the
615qmlAttachedPropertiesObject() function.
620Message *msg = someMessageInstance();
621MessageBoardAttachedType *attached =
622 qobject_cast<MessageBoardAttachedType*>(qmlAttachedPropertiesObject<MessageBoard>(msg));
624qDebug() << "Value of MessageBoard.expired:" << attached->expired();
628\section3 Propagating Attached Properties
630\l QQuickAttachedPropertyPropagator can be subclassed to propagate attached properties
631from a parent object to its children, similar to \l {Control::}{font} and
632\l {Item::}{palette} propagation. It supports propagation through
633\l {Item}{items}, \l {Popup}{popups}, and \l {Window}{windows}.
636\section2 Property Modifier Types
638A property modifier type is a special kind of QML object type. A property
639modifier type instance affects a property (of a QML object instance) which it
640is applied to. There are two different kinds of property modifier types:
642\li property value write interceptors
643\li property value sources
646A property value write interceptor can be used to filter or modify values as
647they are written to properties. Currently, the only supported property
648value write interceptor is the \l Behavior type provided by the \c QtQuick
651A property value source can be used to automatically update the value of a
652property over time. Clients can define their own property value source types.
653The various \l{qtquick-statesanimations-animations.html}{property animation}
654types provided by the \c QtQuick import are examples of property value
657Property modifier type instances can be created and applied to a property of
658a QML object through the "<ModifierType> on <propertyName>" syntax, as the
659following example shows:
673 NumberAnimation on x {
676 loops: Animation.Infinite
683This is commonly referred to as "on" syntax.
685Clients can register their own property value source types, but currently not
686property value write interceptors.
688\section3 Property Value Sources
690\e {Property value sources} are QML types that can automatically update the
691value of a property over time, using the
692\c {<PropertyValueSource> on <property>} syntax. For example, the various
693\l{qtquick-statesanimations-animations.html}{property animation} types
694provided by the \c QtQuick module are examples of property value sources.
696A property value source can be implemented in C++ by subclassing
697QQmlPropertyValueSource and providing an implementation that writes different
698values to a property over time. When the property value source is applied to a
699property using the \c {<PropertyValueSource> on <property>} syntax in QML, it
700is given a reference to this property by the engine so that the property value
703For example, suppose there is a \c RandomNumberGenerator class to be made
704available as a property value source, so that when applied to a QML property,
705it will update the property value to a different random number every 500
706milliseconds. Additionally, a maxValue can be provided to this random number
707generator. This class can be implemented as follows:
710class RandomNumberGenerator : public QObject, public QQmlPropertyValueSource
713 Q_INTERFACES(QQmlPropertyValueSource)
714 Q_PROPERTY(int maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged);
717 RandomNumberGenerator(QObject *parent)
718 : QObject(parent), m_maxValue(100)
720 QObject::connect(&m_timer, SIGNAL(timeout()), SLOT(updateProperty()));
724 int maxValue() const;
725 void setMaxValue(int maxValue);
727 virtual void setTarget(const QQmlProperty &prop) { m_targetProperty = prop; }
730 void maxValueChanged();
733 void updateProperty() {
734 m_targetProperty.write(QRandomGenerator::global()->bounded(m_maxValue));
738 QQmlProperty m_targetProperty;
744When the QML engine encounters a use of \c RandomNumberGenerator as a property
745value source, it invokes \c RandomNumberGenerator::setTarget() to provide the
746type with the property to which the value source has been applied. When the
747internal timer in \c RandomNumberGenerator triggers every 500 milliseconds,
748it will write a new number value to that specified property.
750Once the \c RandomNumberGenerator class has been registered with the QML type
751system, it can be used from QML as a property value source. Below, it is used
752to change the width of a \l Rectangle every 500 milliseconds:
758 width: 300; height: 300
761 RandomNumberGenerator on width { maxValue: 300 }
769In all other respects, property value sources are regular QML types that can
770have properties, signals methods and so on, but with the added capability that
771they can be used to change property values using the
772\c {<PropertyValueSource> on <property>} syntax.
774When a property value source object is assigned to a property, QML first tries
775to assign it normally, as though it were a regular QML type. Only if this
776assignment fails does the engine call the \l
777{QQmlPropertyValueSource::}{setTarget()} method. This allows
778the type to also be used in contexts other than just as a value source.
781\section2 Specifying Default and Parent Properties for QML Object Types
783Any QObject-derived type that is registered as an instantiable QML object type
784can optionally specify a \e {default property} for the type. A default
785property is the property to which an object's children are automatically
786assigned if they are not assigned to any specific property.
788The default property can be set by calling the Q_CLASSINFO() macro for a class
789with a specific "DefaultProperty" value. For example, the \c MessageBoard
790class below specifies its \c messages property as the default property for the
794class MessageBoard : public QObject
797 Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
798 Q_CLASSINFO("DefaultProperty", "messages")
801 QQmlListProperty<Message> messages();
804 QList<Message *> m_messages;
808This enables children of a \c MessageBoard object to be automatically assigned
809to its \c messages property if they are not assigned to a specific property. For
814 Message { author: "Naomi" }
815 Message { author: "Clancy" }
819If \c messages was not set as the default property, then any \c Message objects
820would have to be explicitly assigned to the \c messages property instead, as
826 Message { author: "Naomi" },
827 Message { author: "Clancy" }
832(Incidentally, the \l Item::data property is its default property. Any \l Item
833objects added to this \c data property are also added to the list of
834\l Item::children, so the use of the default property enables visual children
835to be declared for an item without explicitly assigning them to the
836\l{Item::}{children} property.)
838Additionally, you can declare a "ParentProperty" Q_CLASSINFO() to inform the QML
839engine which property should denote the parent object in the QML hierarchy. For
840example, the Message type might be declared as follows:
843class Message : public QObject
846 Q_PROPERTY(QObject* board READ board BINDABLE boardBindable)
847 Q_PROPERTY(QString author READ author BINDABLE authorBindable)
848 Q_CLASSINFO("ParentProperty", "board")
852 Message(QObject *parent = nullptr) : QObject(parent) { m_board = parent; }
854 QObject *board() const { return m_board.value(); }
855 QBindable<QObject *> boardBindable() { return QBindable<QObject *>(&m_board); }
857 QString author() const { return m_author.value(); }
858 QBindable<QString> authorBindable() { return QBindable<QString>(&m_author); }
861 QProperty<QObject *> m_board;
862 QProperty<QString> m_author;
866Defining the parent property affords \l qmllint and other tools better insight
867into the intention of your code and avoids false positive warnings on some
870\section2 Defining Visual Items with the Qt Quick Module
872When building user interfaces with the \l {Qt Quick} module, all QML objects that are
873to be visually rendered must derive from the \l Item type, as it is the base
874type for all visual objects in \l {Qt Quick}. This \l Item type is
875implemented by the QQuickItem C++ class, which is provided by the
876\l {Qt Quick} module. Therefore, this class should be subclassed when it is
877necessary to implement a visual type in C++ that can be integrated into a
878QML-based user interface.
880See the QQuickItem documentation for more information. Additionally, the
881\l{Writing QML Extensions with C++} tutorial demonstrates how a QQuickItem-based
882visual item can be implemented in C++ and integrated into a Qt Quick-based user
886\section1 Receiving Notifications for Object Initialization
888For some custom QML object types, it may be beneficial to delay the
889initialization of particular data until the object has been created and all of
890its properties have been set. For example, this may be the case if the
891initialization is costly, or if the initialization should not be performed until
892all property values have been initialized.
894The \l {Qt QML} module provides the QQmlParserStatus to be subclassed for these
895purposes. It defines a number of virtual methods that are invoked at
896various stages during component instantiation. To receive these notifications, a
897C++ class should inherit QQmlParserStatus and also notify the Qt meta system
898using the Q_INTERFACES() macro.
903class MyQmlType : public QObject, public QQmlParserStatus
906 Q_INTERFACES(QQmlParserStatus)
909 virtual void componentComplete()
911 // Perform some initialization here now that the object is fully created