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
AD

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
m

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:80points,
  • Rating points4
m

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:20points,
  • Rating points-10
Last comments
ИМ
Игорь МаксимовNov. 22, 2024, 11:51 a.m.
Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiOct. 31, 2024, 2:37 p.m.
Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEOct. 19, 2024, 8:19 a.m.
Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовOct. 5, 2024, 7:51 a.m.
Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5July 5, 2024, 11:02 a.m.
QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Now discuss on the forum
Evgenii Legotckoi
Evgenii LegotckoiJune 24, 2024, 3:11 p.m.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Nov. 15, 2024, 6:04 a.m.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectJune 4, 2022, 3:49 a.m.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimOct. 25, 2024, 9:10 a.m.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Follow us in social networks