mafulechka
mafulechkaApril 3, 2020, 4:40 a.m.

What's New in QML in Qt 5.15

While big changes are expected in Qt 6.0, QML has already received some new language features in 5.15. Read on to learn about required properties, built-in components, and nullish coalescing.


Required Properties

Sometimes you have components that require some property to be set and don't really have good defaults. For example, you can take care of the accessibility of your buttons, so you create an AccessibleButton that should always have a description.

// AccessibleButton.qml
Button {
    property string description
    Accessible.description: description
}

However, just because a button has a description property doesn't mean that someone else will set it. So you or your colleague could instantiate the bean at some point with:

AccessibleButton {
    onClicked: (mouse)  => { /* fancy business logic here */ }
}

The description is now just an empty string! Sure, you could give it a default value, but which one? "Button"? It's hardly helpful. "Shouldn't you report it"? At least testing can detect this. But wouldn't it be more useful if the QML engine knows to set this property?

Prior to Qt 5.15, there was unfortunately no way to ensure that the description was set. But since Qt 5.15 it becomes possible:

Button {
    required property string description
    Accessible.description: description
}

Now, if an AccessibleButton is created and no description is given, the entire application won't start. This, however, cannot be done if the component is created dynamically, for example via a Loader. In this case, there will only be a runtime warning.

There are also plans to add more tool support to qmllint and QtCreator to show a warning if required properties are not set.

Required properties and delegates (Delegates)

Also, required properties play a special role in delegates. As you may know, delegates can access model roles of a provided model directly by name, as well as some other properties such as model and index.

ListView {
    model: root.myModel
    delegate: Text {
        id: delegate
        color: index % 2 ? "gray" : "black"
        text: description
    }
}

And, if your delegates do not contain required properties, nothing changes here. However, if they contain at least one required property, those names are no longer available. Instead, you must select exactly by specifying them as required properties.

ListView {
    model: root.myModel
    delegate: Text {
        id: delegate
        required property int index
        required property string description
        color: index % 2 ? "gray" : "black"
        text: description
    }
}

The QML engine will then set the required properties. Note that there is one major difference between the new approach and the old one if your model was editable: with the old approach you could write:

Text {
    id: delegate
    Component.onCompleted: description = "My fancy new text"
}

and the model would be updated accordingly. But if you do

Text {
    id: delegate
    required property string description
    Component.onCompleted: delegate.description = "My fancy new text"
}

then the binding to the description will be broken (and the QML engine will issue a warning) and the model will not be updated. This behavior was chosen to ensure that components do not behave too differently when used in delegates and when used outside of them. Also, the developers didn't want to encourage anyone to make mandatory property assignments (because that would break bindings in general).

If you really want to update the value of the model, of course there is a way to achieve this: make the model a required property and write:

Component.onCompleted: model.description= "My fancy new text"

The developers recommend that you always use required properties on delegates. This avoids unskilled lookups, which are problematic for tools and tend to be slower.

Inline Components

Another new feature in 5.15 is inline components. As the name suggests, they allow you to define a new component within a file. The basic syntax is:

component <component name> : BaseType {
    // declare properties and bindings here
}

Within the file, you can refer to the new component by its name, as if it were defined in its own file. Let's take the LabeledImage component as an example to show how this works:

// Images.qml
import QtQuick 2.15

Item {
    component LabeledImage: Column {
        property alias source: image.source
        property alias caption: text.text

        Image {
            id: image
            width: 50
            height: 50
        }
        Text {
            id: text
            font.bold: true
        }
    }

    Row {
        LabeledImage {
            id: before
            source: "before.png"
            caption: "Before"
        }
        LabeledImage {
            id: after
            source: "after.png"
            caption: "After"
        }
    }
    property LabeledImage selectedImage: before
}

It is also possible to reference the component in other files. In this case, you need to prefix its name to the name of the containing component:

// LabeledImageBox.qml
import QtQuick 2.15

Rectangle {
    property alias caption: image.caption
    property alias source: image.source
    border.width: 2
    border.color: "black"
    Images.LabeledImage {
        id: image
    }
}

You may wonder why inline components are needed when QML already has a Component type. Looking at the previous examples, you can see that inline components allow you to do the following things that Component does not:

• You can instantiate a component without the additional cost of using Loader.
• You can use the component type in property declarations.
• You can refer to a component in other files than the one in which it is defined.

Nullish Coalescing

The latest new language feature was implemented by Qt intern Maximilian Goldstein. While QML generally only supports EcmaScript 6, Max has added support for a new language feature currently in the process of being added to the latest EcmaScript standard: nullish coalescing . Quoting MDN:

nullish coalescing operator is a boolean operator that returns its right operand when its left operand is null or undefined, or otherwise returns its left operand.

Here's an example of how it can be used in QML to set properties from JSON and provide reasonable default values if none were provided.

Item {
    property var settings
    property int brightness: settings.brightness ?? 100
    property color color: settings.color ?? "blue"
    Component.onCompleted: settings = JSON.parse(settingsString)
}

Note that you couldn't use || instead of ?? for brightness (brightness), since settings.brightness could be 0, in which case it would get the default value.

Wait!

With Qt 6 on the horizon, many more changes are sure to come to QML. In addition to modernizing the internals of the QML engine, developers want to use static typing, both to generate faster code (including compiling to C++) and to improve tools. Moreover, while the developers are focusing on these big topics for the initial release of 6.0, they remain open about small quality-of-life improvements: optional chaining or adding support for the fetch API are just two examples of feature requests from the community, a larger timeline is being considered .x (but not the initial version 6.0).

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

Comments

Only authorized users can post comments.
Please, Log in or Sign up
e
  • ehot
  • March 31, 2024, 9:29 p.m.

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
B

C++ - Test 002. Constants

  • Result:16points,
  • Rating points-10
B

C++ - Test 001. The first program and data types

  • Result:46points,
  • Rating points-6
Last comments
k
kmssrFeb. 9, 2024, 2:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 6:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 4:38 p.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 19, 2023, 5:01 a.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
a
a_vlasovApril 14, 2024, 1:41 p.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел ДорофеевApril 14, 2024, 9:35 a.m.
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrexApril 4, 2024, 11:47 a.m.
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
AC
Alexandru CodreanuJan. 19, 2024, 7:57 p.m.
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…

Follow us in social networks