diff options
Diffstat (limited to 'src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc')
-rw-r--r-- | src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc | 259 |
1 files changed, 57 insertions, 202 deletions
diff --git a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc index 7f5e0fa760..1934be6f26 100644 --- a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc +++ b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc @@ -1,35 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qtquick-bestpractices.html \title Best Practices for QML and Qt Quick \brief Lists best practices for working with QML and Qt Quick. \ingroup best-practices +\ingroup explanations-programminglanguages Despite all of the benefits that QML and Qt Quick offer, they can be challenging in certain situations. The following sections elaborate on some of @@ -52,11 +29,16 @@ options that align with the latest UI design trends. If these UI controls do not satisfy your application's needs, only then it is recommended to create a custom control. +You can use the controls when you design UIs in Qt Design Studio. In addition, +it provides timeline-based animations, visual effects, layouts, and a +live-preview for prototyping applications. \section2 Related Information \list \li \l{Qt Quick Controls} +\li \l{Customizing Qt Quick Controls} \li \l{Qt Quick} +\li \l{Qt Design Studio Manual} \endlist \omit @@ -87,66 +69,42 @@ of the target OS. For example, consider the following project directory structure: \badcode -project +MyModule ├── images │ ├── image1.png │ └── image2.png -├── project.pro -└── qml - └── main.qml +├── CMakeLists.txt +└── main.qml \endcode -The following entry in \c project.pro ensures that the resources are built into -the application binary, making them available when needed: +You may represent this structure as a \l{qt_add_qml_module}{CMake QML Module} in the following way: -\badcode - RESOURCES += \ - qml/main.qml \ - images/image1.png \ - images/image2.png -\endcode - -A more convenient approach is to use the -\l {files(pattern[, recursive=false])}{wildcard syntax} to select several files -at once: - -\badcode - RESOURCES += \ - $$files(qml/*.qml) \ - $$files(images/*.png) -\endcode - -This approach is convenient for applications that depend on a limited number -of resources. However, whenever a new file is added to \c RESOURCES using this -approach, it causes \e all of the other files in \c RESOURCES to be recompiled -as well. This can be inefficient, especially for large sets of files. -In this case, a better approach is to separate each type of resource into its -own \l [Qt Core] {Resource Collection Files}{.qrc} file. For example, the snippet -above could be changed to the following: - -\badcode - qml.files = $$files(*.qml) - qml.prefix = /qml - RESOURCES += qml - - images.files = $$files(*.png) - images.prefix = /images - RESOURCES += images +\code +qt_add_qml_module(my_module + URI MyModule + VERSION 1.0 + QML_FILES + main.qml + RESOURCES + images/image1.png + images/image2.png + # ... +) \endcode -Now, whenever a QML file is changed, only the QML files have to be recompiled. +All QML files listed under \c {QML_FILES} will automatically get compiled \l {Ahead-of-Time Compilation}{ahead of time}. -Sometimes it can be necessary to have more control over the path for a -specific file managed by the resource system. For example, if we wanted to give -\c image2.png an alias, we would need to switch to an explicit \c .qrc file. -\l {Creating Resource Files} explains how to do this in detail. +You should keep the QML files in the same directory as the CMakeLists.txt with +the qt_add_qml_module. Otherwise their \l{The Implicit Import}{implicit imports} +will be different from the \l{QML Modules} they belong to. This is a frequent +source of mistakes. \section2 Related Information \list \li \l{The Qt Resource System} \endlist -\section1 Separate UI from Logic +\section1 Separate UI from Business Logic One of the key goals that most application developers want to achieve is to create a maintainable application. One of the ways to achieve this goal is @@ -162,8 +120,8 @@ reasons why an application's UI should be written in QML: \li JavaScript can easily be used in QML to respond to events. \endlist -Being a strongly typed language, C++ is best suited for an application's logic. -Typically, such code performs tasks such as complex calculations +Being a strongly typed language, C++ is best suited for an application's +business logic. Typically, such code performs tasks such as complex calculations or data processing, which are faster in C++ than QML. Qt offers various approaches to integrate QML and C++ code in an application. @@ -174,12 +132,6 @@ sufficient. The following snippet demonstrates examples of models written in QML: \qml - model: ListModel { - ListElement { name: "Item 1" } - ListElement { name: "Item 2" } - ListElement { name: "Item 3" } - } - model: [ "Item 1", "Item 2", "Item 3" ] model: 10 @@ -188,144 +140,47 @@ The following snippet demonstrates examples of models written in QML: Use \l {QAbstractItemModel Subclass}{C++} for dynamic data sets that are large or frequently modified. -\section2 Interacting with QML from C++ - -Although Qt enables you to manipulate QML from C++, it is not recommended to do -so. To explain why, let's take a look at a simplified example. - -\section3 Pulling References from QML - -Suppose we were writing the UI for a settings page: - -\qml - import QtQuick - import QtQuick.Controls - - Page { - Button { - text: qsTr("Restore default settings") - } - } -\endqml - -We want the button to do something in C++ when it is clicked. We know objects -in QML can emit change signals just like they can in C++, so we give the button -an \l [QML]{QtObject::}{objectName} so that we can find it from C++: - -\qml - Button { - objectName: "restoreDefaultsButton" - text: qsTr("Restore default settings") - } -\endqml - -Then, in C++, we find that object and connect to its change signal: - -\code - #include <QGuiApplication> - #include <QQmlApplicationEngine> - #include <QSettings> - - class Backend : public QObject - { - Q_OBJECT - - public: - Backend() {} - - public slots: - void restoreDefaults() { - settings.setValue("loadLastProject", QVariant(false)); - } - - private: - QSettings settings; - }; - - int main(int argc, char *argv[]) - { - QGuiApplication app(argc, argv); - - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); - if (engine.rootObjects().isEmpty()) - return -1; - - Backend backend; - - QObject *rootObject = engine.rootObjects().first(); - QObject *restoreDefaultsButton = rootObject->findChild<QObject*>("restoreDefaultsButton"); - QObject::connect(restoreDefaultsButton, SIGNAL(clicked()), - &backend, SLOT(restoreDefaults())); - - return app.exec(); - } - - #include "main.moc" -\endcode - -With this approach, references to objects are "pulled" from QML. -The problem with this is that the C++ logic layer depends on the QML -presentation layer. If we were to refactor the QML in such a way that the -\c objectName changes, or some other change breaks the ability for the C++ -to find the QML object, our workflow becomes much more complicated and tedious. - -\section3 Pushing References to QML +\section2 Exposing Data from C++ to QML Refactoring QML is a lot easier than refactoring C++, so in order to make maintenance pain-free, we should strive to keep C++ types unaware of QML as much as possible. This can be achieved by "pushing" references to C++ types -into QML: +into QML. -\code - int main(int argc, char *argv[]) - { - QGuiApplication app(argc, argv); - - Backend backend; - - QQmlApplicationEngine engine; - engine.rootContext()->setContextProperty("backend", &backend); - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); - if (engine.rootObjects().isEmpty()) - return -1; - - return app.exec(); - } -\endcode - -The QML then calls the C++ slot directly: - -\qml - import QtQuick - import QtQuick.Controls - - Page { - Button { - text: qsTr("Restore default settings") - onClicked: backend.restoreDefaults() - } - } -\endqml +This can be done by using \l {Required properties}{required properties} and +setting them via \l QQmlApplicationEngine::setInitialProperties. It is also +possible to create one or multiple \l {QML_SINGLETON}{singletons} which will +return all the data the C++ side wants to provide to QML. With this approach, the C++ remains unchanged in the event that the QML needs to be refactored in the future. -In the example above, we set a context property on the root context to expose -the C++ object to QML. This means that the property is available to every -component loaded by the engine. Context properties are useful for objects that -must be available as soon as the QML is loaded and cannot be instantiated in -QML. - For a quick guide to choosing the correct approach to expose C++ types to QML, see \l {Choosing the Correct Integration Method Between C++ and QML}. \section2 Related Information \list -\li \l{Integrating QML and C++} +\li \l{Writing QML Extensions with C++} + {Writing QML Extensions with C++ Tutorial} \li \l{Qt Quick Controls - Chat Tutorial}{Chat application tutorial} \endlist +\section1 Using Qt Design Studio + +Qt Design Studio uses UI files that have the filename extension \e {.ui.qml} +to separate the visual parts of the UI from the UI logic you implement in +\e {.qml} files. You should edit UI files only in the \uicontrol {2D} view in +Qt Design Studio. If you use some other tool to add code that Qt Design Studio +does not support, it displays error messages. Fix the errors to enable visual +editing of the UI files again. Typically, you should move the unsupported code +to a \e {.qml} file. + +\section2 Related Information + +\list + \li \l{Qt Design Studio: UI Files} +\endlist + \section1 Using Qt Quick Layouts Qt offers Qt Quick Layouts to arrange Qt Quick items visually in a layout. @@ -400,7 +255,7 @@ property MyMenu optionsMenu \section1 Performance For information on performance in QML and Qt Quick, -see \l {Performance Considerations And Suggestions}. +see \l {QML Performance Considerations And Suggestions}. \section1 Prefer Declarative Bindings Over Imperative Assignments @@ -480,7 +335,7 @@ developers to follow these tips: With this in place, your application's UI should scale depending on the display resolution on offer. -\image qtquickcontrols2-gallery-welcome.png +\image qtquickcontrols-gallery-welcome.png \section2 Related Information |