diff options
Diffstat (limited to 'src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc')
-rw-r--r-- | src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc | 121 |
1 files changed, 91 insertions, 30 deletions
diff --git a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc index 0a824bb5b5..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 @@ -186,12 +247,12 @@ QMetaObject::invokeMethod(): \endtable Notice the parameter and return type specified after the colon. You can use \l -{QML Basic Types}{basic types} and \l {QML Object Types}{object types} as type +{QML Value Types}{value types} and \l {QML Object Types}{object types} as type names. -If the type is omitted in QML, then you must specify QVariant as type with -Q_RETURN_ARG() and Q_ARG() when calling QMetaObject::invokeMethod. - +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 |