mafulechka
mafulechka3 апреля 2020 г. 4:40

Новые возможности языка QML в Qt 5.15

В то время, как в Qt 6.0 ожидаются большие изменения, QML уже получил некоторые новые языковые возможности в 5.15. Читайте дальше, чтобы узнать об обязательных свойствах, встроенных компонентах и nullish coalescing.


Обязательные свойства (Required Properties)

Иногда у вас есть компоненты, которые требуют установки какого-либо свойства, и в действительности не имеют хороших значений по умолчанию. Например, вы можете позаботиться о доступности ваших кнопок, поэтому вы создаёте AccessibleButton, у которого всегда должно быть описание.

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

Однако тот факт, что кнопка имеет свойство описания, не означает, что ее будет устанавливать кто-либо другой. Таким образом, вы или ваш коллега могли бы в какой-то момент создать экземпляр компонента с помощью:

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

Описание теперь просто пустая строка! Конечно, вы могли бы дать ей значение по умолчанию, но какое именно? "Button" («Кнопка»)? Вряд ли это полезно. "Не должны ли вы сообщить об этом"? По крайней мере, тестирование может это обнаружить. Но не будет ли более полезным, если механизм QML будет знать, что это свойство нужно установить?

До Qt 5.15, к сожалению, не было возможности обеспечить, чтобы описание было установлено. Но начиная с Qt 5.15 это становится возможным:

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

Теперь, если AccessibleButton создан, а описание не задано, все приложение не запустится. Это, однако, не может быть сделано, если компонент создается динамически, например, через Loader. В этом случае будет только предупреждение во время выполнения.

Также планируется добавить дополнительную поддержку инструментов в qmllint и QtCreator, чтобы показывать предупреждение, если требуемые свойства не установлены.

Обязательные свойства и делегаты (Delegates)

Кроме того, обязательные свойства играют особую роль в делегатах. Как вы, возможно, знаете, делегаты могут обращаться к ролям модели предоставленной модели напрямую по имени, а также к некоторым другим свойствам, таким, как модель и индекс.

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

И, если ваши делегаты не содержат обязательных свойств, здесь ничего не меняется. Однако, если они содержат хотя бы одно обязательное свойство, эти имена больше недоступны. Вместо этого вы должны точно выбрать, указав их, как обязательные свойства.

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

Затем механизм QML установит обязательные свойства. Обратите внимание, что между новым подходом и старым есть одно существенное различие в том случае, если ваша модель была редактируемой: при старом подходе вы могли бы написать:

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

и модель, соответственно, была бы обновлена. Но если вы делаете,

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

тогда привязка к описанию будет нарушена (и механизм QML выведет предупреждение), и модель не будет обновлена. Такое поведение было выбрано, чтобы гарантировать, что компоненты не будут вести себя слишком по-разному при использовании в делегатах и при их использовании вне их. Кроме того, разработчики не хотели никого поощрять делать обязательные присваивания свойствам (поскольку это нарушает привязки в целом).

Если вы, действительно, хотите обновить значение модели, конечно, есть способ достичь этого: сделать модель обязательным свойством и написать:

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

Разработчики рекомендуют всегда использовать обязательные свойства в делегатах. Это позволяет избежать неквалифицированных поисков, которые проблематичны для инструментов и, как правило, медленнее.

Встроенные компоненты (Inline Components)

Еще одна новая функция в 5.15 - встроенные компоненты. Как следует из названия, они позволяют вам определить новый компонент внутри файла. Основной синтаксис это:

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

Внутри файла вы можете ссылаться на новый компонент по его имени, как если бы он был определен в его собственном файле. Давайте рассмотрим компонент LabeledImage в качестве примера, чтобы показать, как это работает:

// 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
}

Также есть возможность ссылаться на компонент в других файлах. В этом случае вам нужно добавить префикс его имени к имени содержащего компонента:

// 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
    }
}

Вы можете поинтересоваться, зачем нужны встроенные компоненты, когда QML уже имеет тип Component. Глядя на предыдущие примеры, можно видеть, что встроенные компоненты позволяют вам делать следующие вещи, которые Component не делает:

• Вы можете создать экземпляр компонента без дополнительных затрат на использование Loader.
• Вы можете использовать тип компонента в объявлениях свойств.
• Вы можете ссылаться на компонент в других файлах, отличных от того, в котором он определен.

Nullish Coalescing

Последняя новая языковая функция была реализована стажером компании Qt Максимилианом Гольдштейном. Хотя QML обычно поддерживает только EcmaScript 6, Макс добавил поддержку для новой языковой функции, которая в настоящее время находится в процессе добавления к последнему стандарту EcmaScript: nullish coalescing . Цитируя MDN:

nullish coalescing operator - это логический оператор, который возвращает свой правый операнд, когда его левый операнд равен нулю или не определен, или, в противном случае, возвращает свой левый операнд.

Вот пример того, как его можно использовать в QML для установки свойств из JSON и предоставления разумных значений по умолчанию, если они не были предоставлены.

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

Обратите внимание, что нельзя было использовать || вместо ?? для brightness (яркости), так как settings.brightness мог бы быть 0, в этом случае получили бы значение по умолчанию.

Ожидайте!

С Qt 6 на горизонте, многие другие изменения обязательно появятся в QML. Помимо модернизации внутренних компонентов механизма QML, разработчики хотят использовать статическую типизацию, как для генерирования более быстрого кода (включая компиляцию в C++), так и для улучшения инструментов. Более того, хотя разработчики концентрируются на этих крупных темах для начального выпуска 6.0, они сохраняют открытость относительно небольших улучшений качества жизни: необязательное создание цепочки или добавление поддержки для API выборки - это всего лишь два примера запросов функций от сообщества, рассматривается более крупная временная шкала 6.x (но не начальная версия 6.0).

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
MB

Qt - Тест 001. Сигналы и слоты

  • Результат:57баллов,
  • Очки рейтинга-2
MB

C++ - Тест 001. Первая программа и типы данных

  • Результат:60баллов,
  • Очки рейтинга-1
GK

C++ - Тест 005. Структуры и Классы

  • Результат:0баллов,
  • Очки рейтинга-10
Последние комментарии
J
JonnyJo8 июня 2023 г. 12:14
Qt/C++ - Урок 019. Рисуем треугольник в Qt5. Позиционирование в QGraphicsScene Евгений, здравствуйте! Решил поэкспериментировать немного с кодом из этого урока, нарисовать вместо треугольника квадрат и разобраться с координатами. В итоге, запутался. И ни документация,…
Evgenii Legotckoi
Evgenii Legotckoi25 мая 2023 г. 4:49
Как написать игру на Qt - Урок 2. Анимация героя игры (2D) Код на строчка 184-198 вызывает перерисовку области на каждый 4-й такт счётчика. По той логике не нужно перерисовывать объект постоянно, достаточно реже, чем выполняется игровой слот. А слот вып…
J
JonnyJo21 мая 2023 г. 10:49
Как написать игру на Qt - Урок 2. Анимация героя игры (2D) Евгений, благодарю! Всё равно не совсем понимаю :( Если муха двигает ножками только при нажатии клавиш перемещение, то что, собственно, делает код со строк 184-198 в triangle.cpp? В этих строчка…
Evgenii Legotckoi
Evgenii Legotckoi21 мая 2023 г. 5:57
Как написать игру на Qt - Урок 2. Анимация героя игры (2D) Добрый день. slotGameTimer срабатывает по таймеру и при каждой сработке countForSteps увеличивается на 1, это не зависит от нажатия клавиш, нажатая клавиша лишь определяет положение ножек, котор…
Сейчас обсуждают на форуме
T
Twanger7 июня 2023 г. 11:12
Ошибка при выполнении триггерной функции (GreenPlum) Есть 3 таблицы fact_amount со структурой: CREATE TABLE fact_amount ( id serial4 NOT NULL, fdate date NULL, type_activity_id int4 NULL, status_id int4 NULL, CONSTRAINT fact…
AR
Alexander Ryabikov6 июня 2023 г. 13:35
Работа с QFileSystemModel Вопросик по теме QFileSystemModel в Linux. Он, как и положено, обновляется самостоятельно, если директория локальная. Но, вот, сетевая папка (у меня шара samba) не обновляется. Как её можно…
Evgenii Legotckoi
Evgenii Legotckoi16 апреля 2023 г. 4:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Да, это возможно. Но подобные вещи лучше запускать через celery. То есть drf принимает команду, и после этого регистрирует задачу в celery, котроый уже асинхронно всё это выполняет. В противном …
АБ
Алексей Бобров14 декабря 2021 г. 19:03
Sorting the added QML elements in the ListModel I am writing an alarm clock in QML, I am required to sort the alarms in ascending order (depending on the date or time (if there are several alarms on the same day). I've done the sorting …

Следите за нами в социальных сетях