Укладка QML без ручной маркировки каждого свойства в стиле

Я знаю, что QML не поддерживает стили CSS, например, виджеты, и я читал об альтернативных подходах к стилизации/тематике:

Общим для этих подходов является то, что они требуют, чтобы разработчик указывал части QML, которые можно стилизовать, либо путем привязки к свойству в "стиле QML файла /singleton ", либо с помощью Loader для загрузки другого QML на основе имени стиля. Я бы хотел, чтобы это было похоже на селектор "id" в CSS вместо селектора "class", так что отдельные файлы QML не должны знать, будут ли они введены позже или нет.

Мой текущий подход делает все QML файлы похожими на это (используя подход в ссылке 2):

Main.qml

Rectangle {
    Id: background
    color: g_theme.background.color 
    //g_theme is defined in root context and loaded dynamically
}

Что я хотел бы сделать:

Main.qml

Rectangle {
    Id: background
    color: "green" // default color
}

И затем создайте файл стиля, который определяет (или аналогичный)

Main.qml #background.color: red

Возможно ли это на данный момент или что-то, что находится в стадии разработки для будущей версии Qt, или предпочтительный способ стилизации по-прежнему будет похож на подход, описанный в ссылках выше?

Ответы

Ответ 1

Предпочтительным способом является не применение стиля по компонентам по умолчанию, а выход из этих компонентов для создания предварительно созданных пользовательских компонентов.

Что я делаю для своих проектов:

Во-первых, я создаю один централизованный файл темы в качестве общего модуля JavaScript:

// MyTheme.js
.pragma library;
var bgColor   = "steelblue";
var fgColor   = "darkred";
var lineSize  = 2;
var roundness = 6;

Затем я создаю пользовательские компоненты, которые полагаются на него:

// MyRoundedRect.qml
import QtQuick 2.0;
import "MyTheme.js" as Theme;
Rectangle {
    color: Theme.bgColor;
    border {
        width: Theme.lineSize;
        color: Theme.fgColor;
    }
    radius: Theme.roundness;
}

Затем я могу использовать свой предварительно оформленный компонент всюду с одной строкой кода:

MyRoundedRect { }

И этот метод имеет огромное преимущество: он действительно объектно-ориентированный, а не простой скиннинг.

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

PS: да, вместо JS-модуля можно использовать сингл QML, но он требует дополнительного файла qmldir и поддерживается только с Qt 5.2, что может быть ограничено. И, очевидно, С++ QObject внутри свойства context также будет работать (например, если вы хотите загрузить свойства скина из файла на диске...).

Ответ 2

Также было бы полезно посмотреть стили быстрого управления Qt

При использовании стилей управления нет необходимости явно назначать каждое свойство в целевом элементе управления. Все свойства могут быть определены в отдельном компоненте [ControlName]Style (например, ButtonStyle).
Затем в целевом компоненте (например, Button) вы можете просто ссылаться на компонент стиля в одной строке кода.

Единственный недостаток здесь в том, что компоненты стиля доступны только для Quick Controls Qt. Не для любого компонента Qt.