Best Practices for QML and Qt Quick

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 the best practices that will help you get better results when developing applications.

Custom UI Controls

A fluid and modern UI is key for any application‘s success in today‘s world, and that‘s where QML makes so much sense for a designer or developer. Qt offers the most basic UI controls that are necessary to create a fluid and modern-looking UI. It is recommended to browse this list of UI controls before creating your own custom UI control.

Besides these basic UI controls offered by Qt Quick itself, a rich set of UI controls are also available with Qt Quick Controls 2. They cater to the most common use cases without any change, and offer a lot more possibilities with their customization options. In particular, Qt Quick Controls 2 provides styling 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.

Related Information

Keep it Short and Simple or "KiSS"

QML being a declarative language, a lot of the details are worked out by the underlying engine. So it is important for any QML application, especially one with a larger codebase, to have its code organized in smaller and simpler .qml files.

Related Information

Bundle Application Resources

Most applications depend on resources such as images and icons to provide a rich user experience. It can often be a challenge to make these resources available to the application regardless of the target OS. Most popular OS-es employ stricter security policies that restrict access to the file system, making it harder to load these resources. As an alternative, Qt offers its own resource system that is built into the application binary, enabling access to the application‘s resources regardless of the target OS.

For example, consider the following project directory structure:

project
├── images
│   ├── image1.png
│   └── image2.png
├── project.pro
└── qml
    └── main.qml

The following entry in project.pro ensures that the resources are built into the application binary, making them available when needed:

RESOURCES +=     qml/main.qml     images/image1.png     images/image2.png

A more convenient approach is to use the wildcard syntax to select several files at once:

RESOURCES +=     $$files(qml/*.qml)     $$files(images/*.png)

This approach is convenient for applications that depend on a limited number of resources. However, whenever a new file is added to RESOURCES using this approach, it causes all of the other files in 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 .qrc file. For example, the snippet above could be changed to the following:

qml.files = $$files(*.qml)
qml.prefix = /qml
RESOURCES += qml

images.files = $$files(*.png)
images.prefix = /images
RESOURCES += images

Now, whenever a QML file is changed, only the QML files have to be recompiled.

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 image2.png an alias, we would need to switch to an explicit .qrc file. Creating Resource Files explains how to do this in detail.

Related Information

Separate UI from 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 to separate the user interface from the business logic. The following are a few reasons why an application‘s UI should be written in QML:

  • Declarative languages are strongly suited for defining UIs.
  • QML code is simpler to write, as it is less verbose than C++, and is not strongly typed. This also results in it being an excellent language to prototype in, a quality that is vital when collaborating with designers, for example.
  • JavaScript can easily be used in QML to respond to events.

Being a strongly typed language, C++ is best suited for an application‘s 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. A typical use case is displaying a list of data in a user interface. If the data set is static, simple, and/or small, a model written in QML can be sufficient.

The following snippet demonstrates examples of models written in QML:

model: ListModel {
    ListElement { name: "Item 1" }
    ListElement { name: "Item 2" }
    ListElement { name: "Item 3" }
}

model: [ "Item 1", "Item 2", "Item 3" ]

model: 10

Use C++ for dynamic data sets that are large or frequently modified.

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.

Pulling References from QML

Suppose we were writing the UI for a settings page:

import QtQuick 2.11
import QtQuick.Controls 2.4

Page {
    Button {
        text: qsTr("Restore default settings")
    }
}

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 objectName so that we can find it from C++:

Button {
    objectName: "restoreDefaultsButton"
    text: qsTr("Restore default settings")
}

Then, in C++, we find that object and connect to its change signal:

#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"

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 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.

Pushing References 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:

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();
}

The QML then calls the C++ slot directly:

import QtQuick 2.11
import QtQuick.Controls 2.4

Page {
    Button {
        text: qsTr("Restore default settings")
        onClicked: backend.restoreDefaults()
    }
}

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.

Integrating QML and C++ demonstrates an alternative approach where QML is made aware of a C++ type so that it can instantiate it itself.

Related Information

Using Qt Quick Layouts

Qt offers Qt Quick Layouts to arrange Qt Quick items visually in a layout. Unlike its alternative, the item positioners, the Qt Quick Layouts can also resize its children on window resize. Although Qt Quick Layouts are often the desired choice for most use cases, the following dos and don‘ts must be considered while using them:

Dos

  • Use anchors or the item‘s width and height properties to specify the size of the layout against its parent.
  • Use the Layout attached property to set the size and alignment attributes of the layout‘s immediate children.

Don‘ts

  • Do not rely on anchors to specify the preferred size of an item in a layout. Instead, use Layout.preferredWidth and Layout.preferredHeight.
  • Do not define preferred sizes for items that provide implicitWidth and implicitHeight, unless their implicit sizes are not satisfactory.
  • Do not mix anchors and layouts in ways that cause conflicts. For example, do not apply anchor constraints to a layout‘s immediate children.

    RowLayout {
        id: layout
        anchors.fill: parent
        spacing: 6
        Rectangle {
            color: ‘azure‘
            Layout.fillWidth: true
            Layout.minimumWidth: 50
            Layout.preferredWidth: 100
            Layout.maximumWidth: 300
            Layout.minimumHeight: 150
            Text {
                anchors.centerIn: parent
                text: parent.width + ‘x‘ + parent.height
            }
        }
        Rectangle {
            color: ‘plum‘
            Layout.fillWidth: true
            Layout.minimumWidth: 100
            Layout.preferredWidth: 200
            Layout.preferredHeight: 100
            Text {
                anchors.centerIn: parent
                text: parent.width + ‘x‘ + parent.height
            }
        }
    }

Note: Layouts and anchors are both types of objects that take more memory and instantiation time. Avoid using them (especially in list and table delegates, and styles for controls) when simple bindings to x, y, width, and height properties are enough.

Related Information

Performance

For information on performance in QML and Qt Quick, see Performance Considerations And Suggestions.

Tools and Utilities

For information on useful tools and utilies that make working with QML and Qt Quick easier, see Qt Quick Tools and Utilities.

Scene Graph

For information on Qt Quick‘s scene graph, see Qt Quick Scene Graph.

Scalable User Interfaces

As display resolutions improve, a scalable application UI becomes more and more important. One of the approaches to achieve this is to maintain several copies of the UI for different screen resolutions, and load the appropriate one depending on the available resolution. Although this works pretty well, it adds to the maintenance overhead.

Qt offers a better solution to this problem and recommends the application developers to follow these tips:

  • Use anchors or the Qt Quick Layouts module to lay out the visual items.
  • Do not specify explicit width and height for a visual item.
  • Provide UI resources such as images and icons for each display resolution that your application supports. The Qt Quick Controls 2 gallery example demonstrates this well by providing the qt-logo.png for @2x@3x, and @4x resolutions, enabling the application to cater to high resolution displays. Qt automatically chooses the appropriate image that is suitable for the given display, provided the high DPI scaling feature is explicitly enabled.
  • Use SVG images for small icons. While larger SVGs can be slow to render, small ones work well. Vector images avoid the need to provide several versions of an image, as is necessary with bitmap images.
  • Use font-based icons, such as Font Awesome. These scale to any display resolution, and also allow colorization. The Qt Quick Controls 2 Text Editor example demonstrates this well.

With this in place, your application‘s UI should scale depending on the display resolution on offer.

Related Information

http://doc-snapshots.qt.io/qt5-5.11/qtquick-bestpractices.html

原文地址:https://www.cnblogs.com/findumars/p/8822512.html

时间: 2024-11-02 22:55:25

Best Practices for QML and Qt Quick的相关文章

Qt官方教程翻译——Qt Quick

附网址:http://qt-project.org/doc/qt-5/qtquick-index.html Qt Quick Qt Quick组件是编写QML应用程序的标准库.Qt QML组件提供了QML的引擎和语言基础,Qt Quick组件则提供了QML创建用户图形界面的所有基本类型.它提供了一个可视化的画布,以及创造可视化组件.接收用户输入.创造数据模型和视图.延迟实例化对象等多种类型(types). Qt Quick组件还提供了一个QML API为QML语言创建用户界面提供QML类型,以及

Qt Quick 之 QML 与 C++ 混合编程详解

Qt Quick 技术的引入,使得你能够快速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的,也有很多局限性,原来 Qt 的一些技术,比如低阶的网络编程如 QTcpSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便,所以呢,很多时候我们是会基于这样的原则来混合使用 QML 和 C++: QML 构建界面, C++ 实现非界面的业务逻辑和复杂运算. 请给

从头学Qt Quick(3)-- 用QML写一个简单的颜色选择器

先看一下效果图: 实现功能:点击不同的色块可以改变文字的颜色. 实现步骤: 一.创建一个默认的Qt Quick工程: 二.添加文件Cell.qml 这一步主要是为了实现一个自定义的组件,这个组件就是我们看到的那个色块,很明显定义成组件可以则兼UI的复用. 1 import QtQuick 2.0 2 3 Item { 4 id: container; 5 property alias cellColor: rectangle.color; 6 signal clicked(color cellC

QML官方教程——Using the Qt Quick Particle System

附网址:http://qt-project.org/doc/qt-5/qtquick-effects-particles.html Using the Qt Quick Particle System-- 使用Qt Quick粒子系统 所有粒子系统的类型都可以在QtQuick.Particles模块文档中找到. 注意想要使用粒子模块中的类型,你需要使用下面这个代码进行引入: import QtQuick.Particles 2.0 · The ParticleSystem 粒子系统包含4个主要的

QML官方系列教程——Qt Quick Controls Overview

附网址:http://qt-project.org/doc/qt-5/qtquickcontrols-overview.html Qt Quick Controls Overview -- Qt Quick Controls概述 Qt Quick Controls提供了一套用来在Qt Quick中创建用户界面的UI控件. Getting Started -- 开始 在你的.qml文件中使用以下声明将这些QML类型引入到你的应用程序中. import QtQuick.Controls 1.2 ·

QML官方教程——Qt Quick Layouts Overview

附网址:http://qt-project.org/doc/qt-5/qtquicklayouts-overview.html Qt Quick Layouts Overview -- Qt Quick Layouts概述 Qt Quick Layouts是用来对用户界面中的组件进行布局的一套组件.由于Qt Quick Layouts会根据实际情况动态调整其内部组件的尺寸,因此它非常适合被用在尺寸可变的用户界面中. Getting Started 在.qml文件里使用如下声明将其引入到你的应用程

Qt Quick编程(1)——QML的核心部分ECMAScript

说道QML,不得不先说一下ECMAScript: ECMAScript语言的标准是由Netscape.Sun.微软.Borland等公司基于JavaScript和JScript锤炼.定义出来的. ECMAScript可以为不同种类的宿主环境提供核心的脚本编程能力.ECMAScript仅仅是一个描述,定义了脚本语言的所有属性.方法和对象.它描述了一下内容: 语法 类型 语句 关键字 保留字 运算符 对象 其他语言可以以它为基础拓展出新特性,比如QML引入了Qt对象系统中的信号与槽等特色功能. QM

对Qt for Android的评价(很全面,基本已经没有问题了,网易战网客户端就是Qt quick写的),可以重用QT积累20年的RTL是好事,QML效率是HTML5的5倍

现在Qt不要光看跨平台了,Qt也有能力和原生应用进行较量的.可以直接去Qt官网查看他和那些厂商合作.关于和Java的比较,框架和Java进行比较似乎不且实际.如果是C++和Java比较,网上有很多文章,可自行翻阅,不要在知乎上看C++和Java比较,黑了C++,捧了Python和PHP.Java呢?晾一边了.在安卓上的话,现在问题可能很多,但是随着Qt的更新,大体解决得七七八八了.Qt on Android 对于原有Qt开发人员和爱好者是一个不错的选择,虽然在Qt可以完成大部分安卓的对应功能,可

QML官方系列教程——Qt Quick Controls Styles

附网址:http://qt-project.org/doc/qt-5/qtquickcontrolsstyles-index.html Qt Quick Controls Styles -- Qt Quick控件样式 Qt Quick Controls Styles子模块允许为Qt Quick Controls设置自定义的样式. 它在Qt 5.1中被引入因此需要Qt Quick 2.1. Getting Started -- 开始 使用以下声明将这些QML类型引入到你的应用程序中. import