Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
definetypes.qdoc
Go to the documentation of this file.
1
// Copyright (C) 2017 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
/*!
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
7
8
When extending QML with C++ code, a C++ class can be registered with the QML
9
type system to enable the class to be used as a data type within QML code.
10
While the properties, methods and signals of any QObject-derived class are
11
accessible 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
13
data type from QML until it is registered with the type system. Additionally
14
registration can provide other features, such as allowing a class to be used
15
as an instantiable \l{qtqml-typesystem-objecttypes.html}{QML object type} from
16
QML, or enabling a singleton instance of the class to be imported and used
17
from QML.
18
19
Additionally, the \l {Qt Qml} module provides mechanisms for implementing QML-specific
20
features such as \e{attached properties} and \e{default properties} in C++.
21
22
(Note that a number of the important concepts covered in this document are
23
demonstrated in the \l{Writing QML Extensions with C++} tutorial.)
24
25
\b{NOTE:} All headers that declare QML types need to be accessible without any prefix from the project's include path.
26
27
For more information about C++ and the different QML integration methods,
28
see the
29
\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page.
30
31
\section1 Registering C++ Types with the QML Type System
32
33
A QObject-derived class can be registered with the QML type system to enable the
34
type to be used as a data type from within QML code.
35
36
The engine allows the registration of both instantiable and non-instantiable
37
types. Registering an instantiable type enables a C++ class to be used as the
38
definition of a QML object type, allowing it to be used in object declarations
39
from QML code to create objects of this type. Registration also provides
40
the engine with additional type metadata, enabling the type (and any enums
41
declared by the class) to be used as a data type for property values, method
42
parameters and return values, and signal parameters that are exchanged between
43
QML and C++.
44
45
Registering a non-instantiable type also registers the class as a data type in
46
this manner, but the type cannot be used instantiated as a QML object type
47
from QML. This is useful, for example, if a type has enums that should be
48
exposed to QML but the type itself should not be instantiable.
49
50
For a quick guide to choosing the correct approach to expose C++ types to QML,
51
see \l {Choosing the Correct Integration Method Between C++ and QML}.
52
53
\section2 Preconditions
54
55
All the macros mentioned below are available from the \l qqmlintegration.h
56
header file from the QtQmlIntegration module.
57
58
You need to add the following code to the files using them in order to
59
make the macros available:
60
61
\code
62
#include <QtQmlIntegration/qqmlintegration.h>
63
\endcode
64
65
If you are already linking to the QtQml module, you can instead use the \c
66
qqmlregistration.h header file, which will include \l qqmlintegration.h, as
67
follows:
68
69
\code
70
#include <QtQml/qqmlregistration.h>
71
\endcode
72
73
Furthermore, your class declarations have to live in headers reachable via your
74
project's include path. The declarations are used to generate registration code
75
at compile time, and the registration code needs to include the headers that
76
contain the declarations.
77
78
\section2 Registering an Instantiable Object Type
79
80
\b{Any QObject-derived C++ class can be registered as the definition of a
81
\l{qtqml-typesystem-objecttypes.html}{QML object type}}. Once a
82
class is registered with the QML type system, the class can be declared and
83
instantiated like any other object type from QML code. Once created, a
84
class instance can be manipulated from QML; as
85
\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
86
Types to QML} explains, the properties, methods and signals of any
87
QObject-derived class are accessible from QML code.
88
89
To register a QObject-derived class as an instantiable QML object type, add
90
\c QML_ELEMENT or \c QML_NAMED_ELEMENT(<name>) to the class declaration. You
91
also need to make adjustments in the build system. For qmake, add
92
\c {CONFIG += qmltypes}, a \c {QML_IMPORT_NAME}, and a
93
\c QML_IMPORT_MAJOR_VERSION to your project file. For CMake, the file containing
94
the class should be part of a target set-up with
95
\l{qt_add_qml_module}{qt_add_qml_module()}.
96
This will register the class into the type namespace under the given major version,
97
using either the class name or an explicitly given name as QML type name. The
98
minor version(s) will be derived from any revisions attached to properties,
99
methods, or signals. The default minor version is \c 0. You can explicitly
100
restrict the type to be available only from specific minor versions by adding
101
the \c QML_ADDED_IN_VERSION() macro to the class declaration. Clients can
102
import suitable versions of the namespace in order to use the type.
103
104
For example, suppose there is a \c Message class with \c author and
105
\c creationDate properties:
106
107
\code
108
class Message : public QObject
109
{
110
Q_OBJECT
111
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
112
Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
113
QML_ELEMENT
114
public:
115
// ...
116
};
117
\endcode
118
119
This type can be registered by adding an appropriate type namespace and version
120
number to the project file. For example, to make the type available in the
121
\c com.mycompany.messaging namespace with version 1.0:
122
123
\if defined(onlinedocs)
124
\tab {build-qt-app}{tab-cmake}{CMake}{checked}
125
\tab {build-qt-app}{tab-qmake}{qmake}{}
126
\tabcontent {tab-cmake}
127
\else
128
\section3 Using CMake
129
\endif
130
\badcode
131
qt_add_qml_module(messaging
132
URI com.mycompany.messaging
133
VERSION 1.0
134
SOURCES
135
message.cpp message.h
136
)
137
\endcode
138
\if defined(onlinedocs)
139
\endtabcontent
140
\tabcontent {tab-qmake}
141
\else
142
\section3 Using QMake
143
\endif
144
\badcode
145
CONFIG += qmltypes
146
QML_IMPORT_NAME = com.mycompany.messaging
147
QML_IMPORT_MAJOR_VERSION = 1
148
\endcode
149
150
If the header the class is declared in is not accessible from your project's
151
include path, you may have to amend the include path so that the generated
152
registration code can be compiled.
153
154
\badcode
155
INCLUDEPATH += com/mycompany/messaging
156
\endcode
157
\if defined(onlinedocs)
158
\endtabcontent
159
\endif
160
161
162
163
The type can be used in an \l{qtqml-syntax-basics.html#object-declarations}
164
{object declaration} from QML, and its properties can be read and written to,
165
as per the example below:
166
167
\qml
168
import com.mycompany.messaging
169
170
Message {
171
author: "Amelie"
172
creationDate: new Date()
173
}
174
\endqml
175
176
\section2 Registering Value Types
177
178
Any type with a \l{Q_GADGET} macro can the registered as a
179
\l{qtqml-typesystem-valuetypes.html}{QML value type}. Once such a type is
180
registered with the QML type system it can be used as property type in QML
181
code. Such an instance can be manipulated from QML; as
182
\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++
183
Types to QML} explains, the properties and methods of any value type are
184
accessible from QML code.
185
186
In contrast to object types, value types require \b{lower case} names. The
187
preferred way to register them is using the \l{QML_VALUE_TYPE} or
188
\l{QML_ANONYMOUS} macros. There is no equivalent to \l{QML_ELEMENT} as your
189
C++ classes are typically going to have upper case names. Otherwise the
190
registration is very similar to the registration of object types.
191
192
For example, suppose you want to register a value type \c{person} that consists
193
of two strings for first and last name:
194
195
\code
196
class Person
197
{
198
Q_GADGET
199
Q_PROPERTY(QString firstName READ firstName WRITE setFirstName)
200
Q_PROPERTY(QString lastName READ lastName WRITE setLastName)
201
QML_VALUE_TYPE(person)
202
public:
203
// ...
204
};
205
\endcode
206
207
There are some further limitations on what you can do with value types:
208
\list
209
\li Value types cannot be singletons.
210
\li Value types need to be default-constructible and copy-constructible.
211
\li Using QProperty as a member of a value type is problematic. Value types get
212
copied, and you would need to decide what to do with any bindings on the
213
QProperty at that point. You should not use QProperty in value types.
214
\li Value types cannot provide attached properties.
215
\li The API to define extensions to value types (\l{QML_EXTENDED}) is not public
216
and subject to future changes.
217
\endlist
218
219
\section2 Value Types with Enumerations
220
221
Exposing enumerations from a value type to QML requires some extra steps.
222
223
Value types have lower case names in QML and types with lower case
224
names are generally not addressable in JavaScript code (unless you specify
225
\l{ValueTypeBehavior}{pragma ValueTypeBehavior: Addressable}). If you have
226
a value type in C++ with an enumeration you want to expose to QML, you
227
need to expose the enumeration separately.
228
229
This can be solved by using \l{QML_FOREIGN_NAMESPACE}. First, derive from
230
your value type to create a separate C++ type:
231
232
\code
233
class Person
234
{
235
Q_GADGET
236
Q_PROPERTY(QString firstName READ firstName WRITE setFirstName)
237
Q_PROPERTY(QString lastName READ lastName WRITE setLastName)
238
QML_VALUE_TYPE(person)
239
public:
240
enum TheEnum { A, B, C };
241
Q_ENUM(TheEnum)
242
//...
243
};
244
245
class PersonDerived: public Person
246
{
247
Q_GADGET
248
};
249
\endcode
250
251
Then expose the derived type as a foreign namespace:
252
253
\code
254
namespace PersonDerivedForeign
255
{
256
Q_NAMESPACE
257
QML_NAMED_ELEMENT(Person)
258
QML_FOREIGN_NAMESPACE(PersonDerived)
259
}
260
\endcode
261
262
This produces a \l{qtqml-typesystem-namespaces.html}{QML Namespace}
263
called \c Person (upper case) with an enumeration called \c TheEnum and
264
values \c{A}, \c{B}, and \c{C}. Then you can write the following in QML:
265
266
\qml
267
someProperty: Person.A
268
\endqml
269
270
At the same time you can still use your value type called \c person
271
(lower case) exactly as before.
272
273
\section2 Registering Non-Instantiable Types
274
275
Sometimes a QObject-derived class may need to be registered with the QML type
276
system but not as an instantiable type. For example, this is the case if a C++
277
class:
278
279
\list
280
\li is an interface type that should not be instantiable
281
\li is a base class type that does not need to be exposed to QML
282
\li declares some enum that should be accessible from QML, but otherwise should
283
not be instantiable
284
\li is a type that should be provided to QML through a singleton instance, and
285
should not be instantiable from QML
286
\endlist
287
288
The \l {Qt Qml} module provides several macros for registering non-instantiable
289
types:
290
291
\list
292
\li QML_ANONYMOUS registers a C++ type that is not instantiable and cannot be
293
referred to from QML. This enables the engine to coerce any inherited types that
294
are instantiable from QML.
295
\li QML_INTERFACE registers an existing Qt interface type. The type is
296
not instantiable from QML, and you cannot declare QML properties with it. Using
297
C++ properties of this type from QML will do the expected interface casts,
298
though.
299
\li QML_UNCREATABLE(reason) combined with with QML_ELEMENT or QML_NAMED_ELEMENT
300
registers a named C++ type that is not instantiable but should be identifiable
301
as a type to the QML type system. This is useful if a type's enums or attached
302
properties should be accessible from QML but the type itself should not be
303
instantiable. The parameter should be an error message to be emitted if an
304
attempt at creating an instance of the type is detected.
305
\li QML_SINGLETON combined with QML_ELEMENT or QML_NAMED_ELEMENT registers a
306
singleton type that can be imported from QML, as discussed below.
307
\endlist
308
309
Note that all C++ types registered with the QML type system must be
310
QObject-derived, even if they are non-instantiable.
311
312
313
\section3 Registering Singleton Objects with a Singleton Type
314
315
A singleton type enables properties, signals and methods to be exposed in
316
a namespace without requiring the client to manually instantiate an
317
object instance. QObject singleton types in particular are an efficient and
318
convenient way to provide functionality or global property values.
319
320
Note that singleton types do not have an associated QQmlContext as they are
321
shared across all contexts in an engine. QObject singleton type instances
322
are constructed and owned by the QQmlEngine, and will be destroyed when
323
the engine is destroyed.
324
325
A QObject singleton type can be interacted with in a manner similar to any
326
other QObject or instantiated type, except that only one (engine constructed
327
and owned) instance will exist, and it must be referenced by type name rather
328
than id. Q_PROPERTYs of QObject singleton types may be bound to, and Q_INVOKABLE
329
functions of QObject module APIs may be used in signal handler expressions.
330
This makes singleton types an ideal way to implement styling or theming, and
331
they can also be used instead of ".pragma library" script imports to store global
332
state or to provide global functionality.
333
334
Once registered, a QObject singleton type may be imported and used like any
335
other QObject instance exposed to QML. The following example assumes that
336
a QObject singleton type was registered into the "MyThemeModule" namespace
337
with version 1.0, where that QObject has a QColor "color" Q_PROPERTY:
338
339
\qml
340
import MyThemeModule 1.0 as Theme
341
342
Rectangle {
343
color: Theme.color // binding.
344
}
345
\endqml
346
347
A QJSValue may also be exposed as a singleton type, however clients should
348
be aware that properties of such a singleton type cannot be bound to.
349
350
See \l{QML_SINGLETON} for more information on how implement and
351
register a new singleton type, and how to use an existing singleton type.
352
See \l{Singletons in QML} for more in-depth information about singletons.
353
354
\note Enum values for registered types in QML should start with a capital.
355
356
\section2 Final properties
357
358
Properties declared final using the \c FINAL modifier to \l Q_PROPERTY cannot
359
be overridden. This means that any properties or functions of the same name,
360
declared either in QML or in C++ on derived types, are ignored by the QML
361
engine. You should declare properties \c FINAL when possible, in order to avoid
362
accidental overrides. An override of a property is visible not only in
363
derived classes, but also to QML code executing the context of the base class.
364
Such QML code, typically expects the original property, though. This is a
365
frequent source of mistakes.
366
367
Properties declared \c FINAL can also not be overridden by functions in QML, or
368
by \l Q_INVOKABLE methods in C++.
369
370
\section2 Type Revisions and Versions
371
372
Many of the type registration functions require versions to be specified
373
for the registered type. Type revisions and versions allow new properties
374
or methods to exist in the new version while remaining compatible with
375
previous versions.
376
377
Consider these two QML files:
378
\qml
379
// main.qml
380
import QtQuick 1.0
381
382
Item {
383
id: root
384
MyType {}
385
}
386
\endqml
387
388
\qml
389
// MyType.qml
390
import MyTypes 1.0
391
392
CppType {
393
value: root.x
394
}
395
\endqml
396
397
where \c CppType maps to the C++ class \c CppType.
398
399
If the author of CppType adds a \c root property to CppType in a new
400
version of their type definition, \c root.x now resolves to a different value
401
because \c root is also the \c id of the top level component. The author could
402
specify that the new \c root property is available from a specific minor
403
version. This permits new properties and features to be added to existing
404
types without breaking existing programs.
405
406
The REVISION tag is used to mark the \c root property as added in revision 1
407
of the type. Methods such as Q_INVOKABLE's, signals and slots can also be
408
tagged for a revision using the \l Q_REVISION macro:
409
410
\code
411
class CppType : public BaseType
412
{
413
Q_OBJECT
414
Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION(1, 0))
415
QML_ELEMENT
416
417
signals:
418
Q_REVISION(1, 0) void rootChanged();
419
};
420
\endcode
421
422
The revisions given this way are automatically interpreted as minor versions to
423
the major version given in the project file. In this case, \c root is only
424
available when \c MyTypes version 1.1 or higher is imported. Imports of
425
\c MyTypes version 1.0 remain unaffected.
426
427
For the same reason, new types introduced in later versions should be tagged
428
with the QML_ADDED_IN_VERSION macro.
429
430
This feature of the language allows for behavioural changes to be made
431
without breaking existing applications. Consequently QML module authors
432
should always remember to document what changed between minor versions, and
433
QML module users should check that their application still runs correctly
434
before deploying an updated import statement.
435
436
Revisions of a base class that your type depends upon are automatically
437
registered when registering the type itself. This is useful when deriving
438
from base classes provided by other authors, e.g. when extending classes from
439
the Qt Quick module.
440
441
\note The QML engine does not support revisions for properties or signals of
442
grouped and attached property objects.
443
444
\section2 Registering Extension Objects
445
446
When integrating existing classes and technology into QML, APIs will
447
often need tweaking to fit better into the declarative environment.
448
Although the best results are usually obtained by modifying the original
449
classes directly, if this is either not possible or is complicated by some
450
other concerns, extension objects allow limited extension possibilities to types
451
that you control without direct modifications. Extending Qt's own types is not
452
supported.
453
454
\e{Extension objects} add additional properties to an existing type. An extended
455
type definition allows the programmer to supply an additional type, known as the
456
\e{extension type}, when registering the class. Its members are transparently
457
merged with the original target class when used from within QML. For example:
458
459
\qml
460
QLineEdit {
461
leftMargin: 20
462
}
463
\endqml
464
465
The \c leftMargin property is a new property added to an existing C++ type, \l
466
QLineEdit, without modifying its source code.
467
468
The QML_EXTENDED(extension) macro is for registering extended types. The
469
argument is the name of another class to be used as extension.
470
471
You can also use QML_EXTENDED_NAMESPACE(namespace) to register a namespace, and
472
especially the enumerations declared within, as an extension to a type. If the
473
type you are extending is itself a namespace, you need to use
474
QML_NAMESPACE_EXTENDED(namespace) instead.
475
476
An extension class is a regular QObject, with a constructor that takes a QObject
477
pointer. However, the extension class creation is delayed until the first
478
extended property is accessed. The extension class is created and the target
479
object is passed in as the parent. When the property on the original is
480
accessed, the corresponding property on the extension object is used instead.
481
482
\section2 Registering Foreign Types
483
484
There may be C++ types that cannot be modified to hold the above mentioned
485
macros. Those may be types from 3rdparty libraries, or types that need to
486
fulfill some contract that contradicts the presence of those macros. You can
487
still expose those types to QML, though, using the QML_FOREIGN macro. In order
488
to do this, create a separate struct that consists entirely of the registration
489
macros, like this:
490
491
\code
492
// Contains class Immutable3rdParty
493
#include <3rdpartyheader.h>
494
495
struct Foreign
496
{
497
Q_GADGET
498
QML_FOREIGN(Immutable3rdParty)
499
QML_NAMED_ELEMENT(Accessible3rdParty)
500
QML_ADDED_IN_VERSION(2, 4)
501
// QML_EXTENDED, QML_SINGLETON ...
502
};
503
\endcode
504
505
From this code, you get a QML type with the methods and properties of
506
Immutable3rdParty, and the QML traits (e.g.: singleton, extended) specified in
507
Foreign.
508
509
\section1 Defining QML-Specific Types and Attributes
510
511
\section2 Providing Attached Properties
512
\keyword Integrating QML and C++ - Attached Properties
513
514
In the QML language syntax, there is a notion of \l{Attached properties and
515
attached signal handlers}{\e {attached properties} and \e {attached signal
516
handlers}}, which are additional attributes that are attached to an object.
517
Essentially, such attributes are implemented and provided by an \e {attaching
518
type}, and these attributes may be \e attached to an object of another type.
519
This contrasts with ordinary object properties which are provided by the object
520
type itself (or the object's inherited type).
521
522
For example, the \l Item below uses attached properties and attached handlers:
523
524
\qml
525
import QtQuick 2.0
526
527
Item {
528
width: 100; height: 100
529
530
focus: true
531
Keys.enabled: false
532
Keys.onReturnPressed: console.log("Return key was pressed")
533
}
534
\endqml
535
536
Here, the \l Item object is able to access and set the values of \c Keys.enabled
537
and \c Keys.onReturnPressed. This allows the \l Item object to access these
538
extra attributes as an extension to its own existing attributes.
539
540
\section3 Steps for Implementing Attached Objects
541
542
When considering the above example, there are several parties involved:
543
544
\list
545
\li There is an instance of an anonymous \e {attached object type}, with
546
an \c enabled property and a \c returnPressed signal, that has been attached to
547
the \l Item object to enable it to access and set these attributes.
548
\li The \l Item object is the \e {attachee}, to which the instance of the \e
549
{attached object type} has been attached.
550
\li \l Keys is the \e {attaching type}, which provides the \e {attachee} with a
551
named qualifier, "Keys", through which it may access the attributes of the
552
\e {attached object type}.
553
\endlist
554
555
When the QML engine processes this code, it creates a single instance of the
556
\e {attached object type} and attaches this instance to the \l Item object,
557
thereby providing it with access to the \c enabled and \c returnPressed
558
attributes of the instance.
559
560
The mechanisms for providing attached objects can be implemented from C++ by
561
providing classes for the \e {attached object type} and \e {attaching type}.
562
For the \e{attached object type}, provide a QObject-derived class that defines
563
the attributes to be made accessible to \e attachee objects. For the
564
\e {attaching type}, provide a QObject-derived class that:
565
566
\list
567
\li implements a static qmlAttachedProperties() with the following signature:
568
\code
569
static <AttachedPropertiesType> *qmlAttachedProperties(QObject *object);
570
\endcode
571
572
This method should return an instance of the \e{attached object type}.
573
574
The QML engine invokes this method in order to attach an instance of
575
the attached object type to the \e attachee specified by the \c object
576
parameter. It is customary, though not strictly required, for this method
577
implementation to parent the returned instance to \c object in order
578
to prevent memory leaks.
579
580
This method is called at most once by the engine for each attachee object
581
instance, as the engine caches the returned instance pointer for subsequent
582
attached property accesses. Consequently the attachment object may not be
583
deleted until the attachee \c object is destroyed.
584
585
\li is declared as an attaching type, by adding the QML_ATTACHED(attached) macro
586
to the class declaration. The argument is the name of the
587
\e{attached object type}
588
\endlist
589
590
591
\section3 Implementing Attached Objects: An Example
592
593
For example, take the \c Message type described in an \l{Registering an
594
Instantiable Object Type}{earlier example}:
595
596
\code
597
class Message : public QObject
598
{
599
Q_OBJECT
600
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
601
Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
602
QML_ELEMENT
603
public:
604
// ...
605
};
606
\endcode
607
608
Suppose it is necessary to trigger a signal on a \c Message when it is
609
published to a message board, and also track when the message has expired on
610
the message board. Since it doesn't make sense to add these attributes
611
directly to a \c Message, as the attributes are more relevant to the message
612
board context, they could be implemented as \e attached attributes on a
613
\c Message object that are provided through a "MessageBoard" qualifier. In
614
terms of the concepts described earlier, the parties involved here are:
615
616
\list
617
\li An instance of an anonymous \e{attached object type}, which provides a
618
\c published signal and an \c expired property. This type is implemented by
619
\c MessageBoardAttachedType below
620
\li A \c Message object, which will be the \e attachee
621
\li The \c MessageBoard type, which will be the \e {attaching type} that is
622
used by \c Message objects to access the attached attributes
623
\endlist
624
625
Following is an example implementation. First, there needs to be an
626
\e {attached object type} with the necessary properties and signals that
627
will be accessible to the \e attachee:
628
629
\code
630
class MessageBoardAttachedType : public QObject
631
{
632
Q_OBJECT
633
Q_PROPERTY(bool expired READ expired WRITE setExpired NOTIFY expiredChanged)
634
QML_ANONYMOUS
635
public:
636
MessageBoardAttachedType(QObject *parent);
637
bool expired() const;
638
void setExpired(bool expired);
639
signals:
640
void published();
641
void expiredChanged();
642
};
643
\endcode
644
645
Then the \e {attaching type}, \c MessageBoard, must declare a \c
646
qmlAttachedProperties() method that returns an instance of the
647
\e {attached object type} as implemented by MessageBoardAttachedType.
648
Additionally, \c MessageBoard must be declared as an attaching type
649
via the QML_ATTACHED() macro:
650
651
\code
652
class MessageBoard : public QObject
653
{
654
Q_OBJECT
655
QML_ATTACHED(MessageBoardAttachedType)
656
QML_ELEMENT
657
public:
658
static MessageBoardAttachedType *qmlAttachedProperties(QObject *object)
659
{
660
return new MessageBoardAttachedType(object);
661
}
662
};
663
\endcode
664
665
Now, a \c Message type can access the properties and signals of the attached
666
object type:
667
668
\qml
669
Message {
670
author: "Amelie"
671
creationDate: new Date()
672
673
MessageBoard.expired: creationDate < new Date("January 01, 2015 10:45:00")
674
MessageBoard.onPublished: console.log("Message by", author, "has been
675
published!")
676
}
677
\endqml
678
679
Additionally, the C++ implementation may access the attached object instance
680
that has been attached to any object by calling the
681
qmlAttachedPropertiesObject() function.
682
683
For example:
684
685
\code
686
Message *msg = someMessageInstance();
687
MessageBoardAttachedType *attached =
688
qobject_cast<MessageBoardAttachedType*>(qmlAttachedPropertiesObject<MessageBoard>(msg));
689
690
qDebug() << "Value of MessageBoard.expired:" << attached->expired();
691
\endcode
692
693
694
\section3 Propagating Attached Properties
695
696
\l QQuickAttachedPropertyPropagator can be subclassed to propagate attached properties
697
from a parent object to its children, similar to \l {Control::}{font} and
698
\l {Item::}{palette} propagation. It supports propagation through
699
\l {Item}{items}, \l {Popup}{popups}, and \l {Window}{windows}.
700
701
702
\section2 Property Modifier Types
703
704
A property modifier type is a special kind of QML object type. A property
705
modifier type instance affects a property (of a QML object instance) which it
706
is applied to. There are two different kinds of property modifier types:
707
\list
708
\li property value write interceptors
709
\li property value sources
710
\endlist
711
712
A property value write interceptor can be used to filter or modify values as
713
they are written to properties. Currently, the only supported property
714
value write interceptor is the \l Behavior type provided by the \c QtQuick
715
import.
716
717
A property value source can be used to automatically update the value of a
718
property over time. Clients can define their own property value source types.
719
The various \l{qtquick-statesanimations-animations.html}{property animation}
720
types provided by the \c QtQuick import are examples of property value
721
sources.
722
723
Property modifier type instances can be created and applied to a property of
724
a QML object through the "<ModifierType> on <propertyName>" syntax, as the
725
following example shows:
726
727
\qml
728
import QtQuick 2.0
729
730
Item {
731
width: 400
732
height: 50
733
734
Rectangle {
735
width: 50
736
height: 50
737
color: "red"
738
739
NumberAnimation on x {
740
from: 0
741
to: 350
742
loops: Animation.Infinite
743
duration: 2000
744
}
745
}
746
}
747
\endqml
748
749
This is commonly referred to as "on" syntax.
750
751
Clients can register their own property value source types, but currently not
752
property value write interceptors.
753
754
\section3 Property Value Sources
755
756
\e {Property value sources} are QML types that can automatically update the
757
value of a property over time, using the
758
\c {<PropertyValueSource> on <property>} syntax. For example, the various
759
\l{qtquick-statesanimations-animations.html}{property animation} types
760
provided by the \c QtQuick module are examples of property value sources.
761
762
A property value source can be implemented in C++ by subclassing
763
QQmlPropertyValueSource and providing an implementation that writes different
764
values to a property over time. When the property value source is applied to a
765
property using the \c {<PropertyValueSource> on <property>} syntax in QML, it
766
is given a reference to this property by the engine so that the property value
767
can be updated.
768
769
For example, suppose there is a \c RandomNumberGenerator class to be made
770
available as a property value source, so that when applied to a QML property,
771
it will update the property value to a different random number every 500
772
milliseconds. Additionally, a maxValue can be provided to this random number
773
generator. This class can be implemented as follows:
774
775
\code
776
class RandomNumberGenerator : public QObject, public QQmlPropertyValueSource
777
{
778
Q_OBJECT
779
Q_INTERFACES(QQmlPropertyValueSource)
780
Q_PROPERTY(int maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged);
781
QML_ELEMENT
782
public:
783
RandomNumberGenerator(QObject *parent)
784
: QObject(parent), m_maxValue(100)
785
{
786
QObject::connect(&m_timer, SIGNAL(timeout()), SLOT(updateProperty()));
787
m_timer.start(500);
788
}
789
790
int maxValue() const;
791
void setMaxValue(int maxValue);
792
793
virtual void setTarget(const QQmlProperty &prop) { m_targetProperty = prop; }
794
795
signals:
796
void maxValueChanged();
797
798
private slots:
799
void updateProperty() {
800
m_targetProperty.write(QRandomGenerator::global()->bounded(m_maxValue));
801
}
802
803
private:
804
QQmlProperty m_targetProperty;
805
QTimer m_timer;
806
int m_maxValue;
807
};
808
\endcode
809
810
When the QML engine encounters a use of \c RandomNumberGenerator as a property
811
value source, it invokes \c RandomNumberGenerator::setTarget() to provide the
812
type with the property to which the value source has been applied. When the
813
internal timer in \c RandomNumberGenerator triggers every 500 milliseconds,
814
it will write a new number value to that specified property.
815
816
Once the \c RandomNumberGenerator class has been registered with the QML type
817
system, it can be used from QML as a property value source. Below, it is used
818
to change the width of a \l Rectangle every 500 milliseconds:
819
820
\qml
821
import QtQuick 2.0
822
823
Item {
824
width: 300; height: 300
825
826
Rectangle {
827
RandomNumberGenerator on width { maxValue: 300 }
828
829
height: 100
830
color: "red"
831
}
832
}
833
\endqml
834
835
In all other respects, property value sources are regular QML types that can
836
have properties, signals methods and so on, but with the added capability that
837
they can be used to change property values using the
838
\c {<PropertyValueSource> on <property>} syntax.
839
840
When a property value source object is assigned to a property, QML first tries
841
to assign it normally, as though it were a regular QML type. Only if this
842
assignment fails does the engine call the \l
843
{QQmlPropertyValueSource::}{setTarget()} method. This allows
844
the type to also be used in contexts other than just as a value source.
845
846
847
\section2 Specifying Default and Parent Properties for QML Object Types
848
849
Any QObject-derived type that is registered as an instantiable QML object type
850
can optionally specify a \e {default property} for the type. A default
851
property is the property to which an object's children are automatically
852
assigned if they are not assigned to any specific property.
853
854
The default property can be set by calling the Q_CLASSINFO() macro for a class
855
with a specific "DefaultProperty" value. For example, the \c MessageBoard
856
class below specifies its \c messages property as the default property for the
857
class:
858
859
\code
860
class MessageBoard : public QObject
861
{
862
Q_OBJECT
863
Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
864
Q_CLASSINFO("DefaultProperty", "messages")
865
QML_ELEMENT
866
public:
867
QQmlListProperty<Message> messages();
868
869
private:
870
QList<Message *> m_messages;
871
};
872
\endcode
873
874
This enables children of a \c MessageBoard object to be automatically assigned
875
to its \c messages property if they are not assigned to a specific property. For
876
example:
877
878
\qml
879
MessageBoard {
880
Message { author: "Naomi" }
881
Message { author: "Clancy" }
882
}
883
\endqml
884
885
If \c messages was not set as the default property, then any \c Message objects
886
would have to be explicitly assigned to the \c messages property instead, as
887
follows:
888
889
\qml
890
MessageBoard {
891
messages: [
892
Message { author: "Naomi" },
893
Message { author: "Clancy" }
894
]
895
}
896
\endqml
897
898
(Incidentally, the \l Item::data property is its default property. Any \l Item
899
objects added to this \c data property are also added to the list of
900
\l Item::children, so the use of the default property enables visual children
901
to be declared for an item without explicitly assigning them to the
902
\l{Item::}{children} property.)
903
904
Additionally, you can declare a "ParentProperty" Q_CLASSINFO() to inform the QML
905
engine which property should denote the parent object in the QML hierarchy. For
906
example, the Message type might be declared as follows:
907
908
\code
909
class Message : public QObject
910
{
911
Q_OBJECT
912
Q_PROPERTY(QObject* board READ board BINDABLE boardBindable)
913
Q_PROPERTY(QString author READ author BINDABLE authorBindable)
914
Q_CLASSINFO("ParentProperty", "board")
915
QML_ELEMENT
916
917
public:
918
Message(QObject *parent = nullptr) : QObject(parent) { m_board = parent; }
919
920
QObject *board() const { return m_board.value(); }
921
QBindable<QObject *> boardBindable() { return QBindable<QObject *>(&m_board); }
922
923
QString author() const { return m_author.value(); }
924
QBindable<QString> authorBindable() { return QBindable<QString>(&m_author); }
925
926
private:
927
QProperty<QObject *> m_board;
928
QProperty<QString> m_author;
929
};
930
\endcode
931
932
Defining the parent property affords \l{qmllint} and other tools better insight
933
into the intention of your code and avoids false positive warnings on some
934
property accesses.
935
936
\section2 Defining Visual Items with the Qt Quick Module
937
938
When building user interfaces with the \l {Qt Quick} module, all QML objects that are
939
to be visually rendered must derive from the \l Item type, as it is the base
940
type for all visual objects in \l {Qt Quick}. This \l Item type is
941
implemented by the QQuickItem C++ class, which is provided by the
942
\l {Qt Quick} module. Therefore, this class should be subclassed when it is
943
necessary to implement a visual type in C++ that can be integrated into a
944
QML-based user interface.
945
946
See the QQuickItem documentation for more information. Additionally, the
947
\l{Writing QML Extensions with C++} tutorial demonstrates how a QQuickItem-based
948
visual item can be implemented in C++ and integrated into a Qt Quick-based user
949
interface.
950
951
952
\section1 Receiving Notifications for Object Initialization
953
954
For some custom QML object types, it may be beneficial to delay the
955
initialization of particular data until the object has been created and all of
956
its properties have been set. For example, this may be the case if the
957
initialization is costly, or if the initialization should not be performed until
958
all property values have been initialized.
959
960
The \l {Qt Qml} module provides the QQmlParserStatus to be subclassed for these
961
purposes. It defines a number of virtual methods that are invoked at
962
various stages during component instantiation. To receive these notifications, a
963
C++ class should inherit QQmlParserStatus and also notify the Qt meta system
964
using the Q_INTERFACES() macro.
965
966
For example:
967
968
\code
969
class MyQmlType : public QObject, public QQmlParserStatus
970
{
971
Q_OBJECT
972
Q_INTERFACES(QQmlParserStatus)
973
QML_ELEMENT
974
public:
975
virtual void componentComplete()
976
{
977
// Perform some initialization here now that the object is fully created
978
}
979
};
980
\endcode
981
982
\sa {qqmlintegration.h}{QML Type Registration Macros}, {Overview - QML and C++ Integration}
983
*/
qtdeclarative
src
qml
doc
src
cppintegration
definetypes.qdoc
Generated on
for Qt by
1.16.1