aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc')
-rw-r--r--src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc259
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