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
andLayout.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
- Gallery example
- Text Editor example
- Font Awesome
- Scalability
- High DPI Displays
http://doc-snapshots.qt.io/qt5-5.11/qtquick-bestpractices.html
Best Practices for QML and Qt Quick的更多相关文章
- qml(Qt Quick)做界面
qml(Qt Quick)做界面 来源 https://www.zhihu.com/question/24880681/answer/29324824 本人是Qt初学者,正在写一个会计小软件(Lin ...
- Qt Widgets、QML、Qt Quick的区别
Qt Widgets.QML.Qt Quick的区别 简述 看了之前关于 QML 的一些介绍,很多人难免会有一些疑惑: Q1:QML 和 Qt Quick 之间有什么区别? Q2:QtQuick 1. ...
- QML、Qt Quick
当用widget开发Qt时, 语言:C++ 库:Qt库 当用QML开发时, 语言:QML 库:Qt Quick
- Qt Quick 与 QML语言(初学笔记1)
Qt Quick Qt Quick是一些新的UI技术的集合,用来帮助开发者创建一种现在越来越多用于手机.多媒体播放器.机顶盒以及其他便携式设备上的直观的.现代的.流畅的用户界面.简单来说,Qt Qui ...
- qt quick中qml编程语言
Qt QML 入门 — 使用C++定义QML类型 发表于 2013 年 3 月 11 日 注册C++类 注册可实例化的类型 注册不实例化的QML类型 附带属性 注册C++类 注册可实例化的类型 如 ...
- Qt Quick QMl学习笔记 之图片浏览器
Qt Quick模块是编写QML应用程序的标准库.虽然Qt QML模块提供QML引擎和语言基础结构,但Qt Quick模块提供了使用QML创建用户界面所需的所有基本类型.它提供了一个可视画布,包括用于 ...
- Qt Quick Controls 与 Qt Quick Controls 2的区别(详细对照)
Qt Quick Controls 原本是为支持桌面平台而开发的,后来又加入了移动平台和嵌入式平台的支持.它们应用非常广泛,因为它们提供了足够灵活的样式系统,以允许开发具有平台相关或者无关风格的应用程 ...
- 从头学Qt Quick(3)-- 用QML写一个简单的颜色选择器
先看一下效果图: 实现功能:点击不同的色块可以改变文字的颜色. 实现步骤: 一.创建一个默认的Qt Quick工程: 二.添加文件Cell.qml 这一步主要是为了实现一个自定义的组件,这个组件就是我 ...
- 对Qt for Android的评价(很全面,基本已经没有问题了,网易战网客户端就是Qt quick写的),可以重用QT积累20年的RTL是好事,QML效率是HTML5的5倍
现在Qt不要光看跨平台了,Qt也有能力和原生应用进行较量的.可以直接去Qt官网查看他和那些厂商合作.关于和Java的比较,框架和Java进行比较似乎不且实际.如果是C++和Java比较,网上有很多文章 ...
随机推荐
- Android手机间使用socket进行文件互传实例
这是一个Android手机间文件传输的例子,两个手机同时装上此app,然后输入接收端的ip,选择文件,可以多选,点确定,就发送到另一个手机,一个简单快捷文件快传实例.可以直接运用到项目中. 下面是文件 ...
- FineUI 页面跳转
要加 EnableAjax=false; <f:Button ID="btn1" EnableAjax="false" OnClick="btn ...
- BZOJ2780: [Spoj]8093 Sevenk Love Oimaster(广义后缀自动机,Parent树,Dfs序)
Description Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXu ...
- 【习题 7-4 UVA-818】Cutting Chains
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 二进制枚举要解开哪些环. 把所有和它相关的边都删掉. 对于剩下的联通分量. 看看是不是每一个联通分量都是一条链 ->每个点的度 ...
- windows服务插件利器-新生命组件XAgent使用心得
1.简单介绍 XAgent为大石头带领下的新生命团队自己开发的一个.Net下的常用的Windows服务管理组件利器,通过在控制台中简单的输入1,2,3,4,5等数字可以实现一步安装.卸载Windows ...
- 洛谷—— P1190 接水问题
https://www.luogu.org/problem/show?pid=1190#sub 题目描述 学校里有一个水房,水房里一共装有 m 个龙头可供同学们打开水,每个龙头每秒钟的 供水量相等,均 ...
- Http请求连接池 - HttpClient 的 PoolingHttpClientConnectionManager
两个主机建立连接的过程是非常复杂的一个过程,涉及到多个数据包的交换,而且也非常耗时间.Http连接须要的三次握手开销非常大,这一开销对于比較小的http消息来说更大.但是假设我们直接使用已经建立好的h ...
- libiconv 支持的编码
libiconv 支持的编码 php 中的 iconv() 函数常用来作编码转换用.作一些不同编码的动态数据的转换时常遇到一些未知编码的数据,这时 iconv() 支持那些编码转换就很重要. 刚开始, ...
- 1.JPA概要
转自:https://www.cnblogs.com/holbrook/archive/2012/12/30/2839842.html JPA定义了Java ORM及实体操作API的标准.本文摘录了J ...
- docker进入容器的几种方法
一 启动进入容器指定bash 退出后容器关闭 [root@Centos-node3 ~]# docker run -it centos bash [root@83c6b25aca09 /]# 二 do ...