diff options
Diffstat (limited to 'src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc')
-rw-r--r-- | src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc | 146 |
1 files changed, 105 insertions, 41 deletions
diff --git a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc index 9c33979f40..eb866eb843 100644 --- a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc +++ b/src/qml/doc/src/cppintegration/interactqmlfromcpp.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-interactqmlfromcpp.html \title Interacting with QML Objects from C++ @@ -41,6 +17,9 @@ into a C++ application. Once a QML object is created, it can be inspected from C++ in order to read and write to properties, invoke methods and receive signal notifications. +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 Loading QML Objects from C++ @@ -105,6 +84,88 @@ You can also connect to any signals or call methods defined in the component using QMetaObject::invokeMethod() and QObject::connect(). See \l {Invoking QML Methods} and \l {Connecting to QML Signals} below for further details. +\section1 Accessing QML Objects via well-defined C++ Interfaces + +The best way of interacting with QML from C++ is to define an interface for +doing so in C++ and accessing it in QML itself. With other methods, refactoring +your QML code can easily lead to your QML / C++ interaction breaking. It also +helps to reason about the interaction of QML and C++ code, as having it driven +via QML can be more easily reasoned about by both users and tooling such as +qmllint. Accessing QML from C++ will lead to QML code that cannot be understood +without manually verifying that no outside C++ code is modifying a given QML +component, and even then the extent of the access might change over time, making +continued use of this strategy a maintenance burden. + +To let QML drive the interaction, first you need to define a C++ interface: + +\code +class CppInterface : public QObject +{ + Q_OBJECT + QML_ELEMENT + // ... +}; +\endcode + +Using a QML-driven approach, this interface can be interacted with in two ways: + +\section2 Singletons + +One option is to register the interface as a singleton by adding the \l +QML_SINGLETON macro to the interface, exposing it to all components. Following +that, the interface becomes available via a simple import statement: + +\code +import my.company.module + +Item { + Component.onCompleted: { + CppInterface.foo(); + } +} +\endcode + +Use this approach if you need your interface in more places than the root component, as +simply passing down an object would require explicitly passing it on to other +components via a property or utilizing the slow and not recommended method of +using \l {Unqualified access}{unqualified access}. + +\section2 Initial properties + +Another option is to mark the interface as uncreatable via \l QML_UNCREATABLE +and supplying it to the root QML Component by using \l +QQmlComponent::createWithInitialProperties() and a \l {Required +Properties}{required property} on the QML end. + +Your root component may look something like this: + +\code +import QtQuick + +Item { + required property CppInterface interface + Component.onCompleted: { + interface.foo(); + } +} +\endcode + +Marking the property as required here protects the component against being +created without the interface property being set. + +You can then initialize your component in the same way as outlined in \l +{Loading QML Objects from C++} except using \c {createWithInitialProperties()}: + +\code + component.createWithInitialProperties(QVariantMap{{u"interface"_s, QVariant::fromValue<CppInterface *>(new CppInterface)}}); +\endcode + +This method is to be preferred if you know that your interface only needs to be +available to the root component. It also allows for connecting to signals and +slots of the interface more easily on the C++ side. + +If neither of these methods suit your needs you may want to investigate the usage of +\l {Using C++ Models with Qt Quick Views}{C++ models} instead. \section1 Accessing Loaded QML Objects by Object Name @@ -166,9 +227,12 @@ updated, and any \c onButtonTextChanged handlers would not be called. \section2 Invoking QML Methods -All QML methods are exposed to the meta-object system and can be called from C++ -using QMetaObject::invokeMethod(). Method parameters and return values passed -from QML are always translated into QVariant values in C++. +All QML methods are exposed to the meta-object system and can be called from +C++ using QMetaObject::invokeMethod(). You can specify types for the parameters +and the return value after the colon character, as shown in the code snippet +below. This can be useful, for example, when you want to connect a signal in +C++ with a certain signature to a QML-defined method. If you omit the types, +the C++ signature will use QVariant. Here is a C++ application that calls a QML method using QMetaObject::invokeMethod(): @@ -182,10 +246,13 @@ QMetaObject::invokeMethod(): \li \snippet qml/qtbinding/functions-qml/main.cpp 0 \endtable -Notice the Q_RETURN_ARG() and Q_ARG() arguments for QMetaObject::invokeMethod() -must be specified as QVariant types, as this is the generic data type used for -QML method parameters and return values. +Notice the parameter and return type specified after the colon. You can use \l +{QML Value Types}{value types} and \l {QML Object Types}{object types} as type +names. +If the type is omitted or specified as \c var in QML, then you must pass +QVariant as type with Q_RETURN_ARG() and Q_ARG() when calling +QMetaObject::invokeMethod. \section2 Connecting to QML Signals @@ -210,9 +277,8 @@ QObject::connect(), so that the \c cppSlot() method is called whenever the \snippet qml/qtbinding/signals-qml/main.cpp 0 \endtable -When a QML object type is used as a signal parameter, the parameter should -use \l var as the type, and the value should be received in C++ using the -QVariant type: +A QML object type in a signal parameter is translated to a pointer to the class +in C++: \table \row @@ -226,7 +292,7 @@ QVariant type: id: item width: 100; height: 100 - signal qmlSignal(var anObject) + signal qmlSignal(anObject: Item) MouseArea { anchors.fill: parent @@ -241,18 +307,16 @@ QVariant type: { Q_OBJECT public slots: - void cppSlot(const QVariant &v) { - qDebug() << "Called the C++ slot with value:" << v; + void cppSlot(QQuickItem *item) { + qDebug() << "Called the C++ slot with item:" << item; - QQuickItem *item = - qobject_cast<QQuickItem*>(v.value<QObject*>()); qDebug() << "Item dimensions:" << item->width() << item->height(); } }; int main(int argc, char *argv[]) { - QApplication app(argc, argv); + QGuiApplication app(argc, argv); QQuickView view(QUrl::fromLocalFile("MyItem.qml")); QObject *item = view.rootObject(); |