diff options
Diffstat (limited to 'src/qml/doc/src/cppintegration/exposecppattributes.qdoc')
-rw-r--r-- | src/qml/doc/src/cppintegration/exposecppattributes.qdoc | 142 |
1 files changed, 99 insertions, 43 deletions
diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc index 618ed1e334..6031d0eebb 100644 --- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc +++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qtqml-cppintegration-exposecppattributes.html \title Exposing Attributes of C++ Types to QML @@ -32,9 +8,9 @@ QML can easily be extended with functionality defined in C++ code. Due to the tight integration of the QML engine with the \l{The Meta-Object System}{Qt meta-object system}, any functionality that is appropriately exposed by a -QObject-derived class is accessible from QML code. This enables C++ data and -functions to be accessible directly from QML, often with little or no -modification. +QObject-derived class or a Q_GADGET type is accessible from QML code. This +enables C++ data and functions to be accessible directly from QML, often with +little or no modification. The QML engine has the ability to introspect QObject instances through the meta-object system. This means any QML code can access the following members of @@ -46,7 +22,7 @@ an instance of a QObject-derived class: \li Signals \endlist -(Additionally, enums are available if they have been declared with Q_ENUMS. +(Additionally, enums are available if they have been declared with Q_ENUM. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++} for more details.) @@ -56,11 +32,27 @@ system}{registered with the QML type system}. However, if a class is to be used in a way that requires the engine to access additional type information — for example, if the class itself is to be used as a method parameter or property, or if one of its enum types is to be used in this way — then the -class may need to be registered. +class may need to be registered. Registration is recommended for all types you +use in QML, as only registered types can be analyzed at compile time. + +Registration is required for Q_GADGET types, as they don't derive from a known +common base and can't be made available automatically. Without registration, +their properties and methods are inaccessible. + +You can make C++ types from a different module available in your own module by +adding a dependency to your \l{qt_add_qml_module} call using the \e DEPENDENCIES +option. You may, for example, want to depend on QtQuick so that your QML-exposed +C++ types can use \l QColor as method arguments and return values. QtQuick +exposes \l QColor as a \l {QML Value Types}{value type} \e color. Such +dependencies may be automatically inferred at run time, but you should not rely +on this. Also note that a number of the important concepts covered in this document are demonstrated in the \l{Writing QML Extensions with C++} tutorial. +For more information about C++ and the different QML integration methods, +see the +\l {Overview - QML and C++ Integration} {C++ and QML integration overview} page. \section1 Data Type Handling and Ownership @@ -85,7 +77,7 @@ A \e property can be specified for any QObject-derived class using the Q_PROPERTY() macro. A property is a class data member with an associated read function and optional write function. -All properties of a QObject-derived class are accessible from QML. +All properties of a QObject-derived or Q_GADGET class are accessible from QML. For example, below is a \c Message class with an \c author property. As specified by the Q_PROPERTY macro call, this property is readable through @@ -99,7 +91,8 @@ Instead of: \badcode using FooEnum = Foo::Enum; -class Bar : public QObject { +class Bar : public QObject +{ Q_OBJECT Q_PROPERTY(FooEnum enum READ enum WRITE setEnum NOTIFY enumChanged) }; @@ -108,37 +101,46 @@ class Bar : public QObject { Refer to the type directly: \code -class Bar : public QObject { +class Bar : public QObject +{ Q_OBJECT Q_PROPERTY(Foo::Enum enum READ enum WRITE setEnum NOTIFY enumChanged) }; \endcode +In order to make \c Message available you need to use \l{QML_ELEMENT} in C++ +and \l{qt_add_qml_module} in CMake. + \code class Message : public QObject { Q_OBJECT + QML_ELEMENT Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) public: - void setAuthor(const QString &a) { + void setAuthor(const QString &a) + { if (a != m_author) { m_author = a; emit authorChanged(); } } - QString author() const { + + QString author() const + { return m_author; } + signals: void authorChanged(); + private: QString m_author; }; \endcode -If an instance of this class was \l{Embedding C++ Objects into QML with Context -Properties}{set as a context property} when loading a file named \c MyItem.qml -from C++: +An instance of \c Message can be passed as required property to a file called +\c MyItem.qml to make it available: \code int main(int argc, char *argv[]) { @@ -146,7 +148,7 @@ from C++: QQuickView view; Message msg; - view.engine()->rootContext()->setContextProperty("msg", &msg); + view.setInitialProperties({{"msg", &msg}}); view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show(); @@ -158,9 +160,11 @@ Then, the \c author property could be read from \c MyItem.qml: \qml // MyItem.qml -import QtQuick 2.0 +import QtQuick Text { + required property Message msg + width: 100; height: 100 text: msg.author // invokes Message::author() to get this value @@ -397,6 +401,8 @@ that is a public slot: class MessageBoard : public QObject { Q_OBJECT + QML_ELEMENT + public: Q_INVOKABLE bool postMessage(const QString &msg) { qDebug() << "Called the C++ method with" << msg; @@ -410,7 +416,7 @@ that is a public slot: }; \endcode -If an instance of \c MessageBoard was set as the context data for a file \c +If an instance of \c MessageBoard was set as the required property for a file \c MyItem.qml, then \c MyItem.qml could invoke the two methods as shown in the examples below: @@ -424,7 +430,7 @@ examples below: MessageBoard msgBoard; QQuickView view; - view.engine()->rootContext()->setContextProperty("msgBoard", &msgBoard); + view.setInitialProperties({{"msgBoard", &msgBoard}}); view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show(); @@ -439,6 +445,8 @@ examples below: import QtQuick 2.0 Item { + required property MessageBoard msgBoard + width: 100; height: 100 MouseArea { @@ -464,6 +472,54 @@ be called according to the number and the types of arguments that are provided. Values returned from C++ methods are converted to JavaScript values when accessed from JavaScript expressions in QML. +\section2 C++ methods and the 'this' object + +You may want to retrieve a C++ method from one object and call it on a different +object. Consider the following example, within a QML module called \c{Example}: + +\table +\row +\li C++ +\li +\code +class Invokable : public QObject +{ + Q_OBJECT + QML_ELEMENT +public: + Invokable(QObject *parent = nullptr) : QObject(parent) {} + + Q_INVOKABLE void invoke() { qDebug() << "invoked on " << objectName(); } +}; +\endcode +\row +\li QML +\li +\qml +import QtQml +import Example + +Invokable { + objectName: "parent" + property Invokable child: Invokable {} + Component.onCompleted: child.invoke.call(this) +} +\endqml +\endtable + +If you load the QML code from a suitable main.cpp, it should print +"invoked on parent". However, due to a long standing bug, it doesn't. +Historically, the 'this' object of C++-based methods is inseparably bound to +the method. Changing this behavior for existing code would cause subtle errors +since the 'this' object is implicit in many places. Since Qt 6.5 you can +explicitly opt into the correct behavior and allow C++ methods to accept a +'this' object. To do so, add the following pragma to your QML documents: + +\qml +pragma NativeMethodBehavior: AcceptThisObject +\endqml + +With this line added, the example above will work as expected. \section1 Exposing Signals |