样式化QML而无需手动标记要设置样式的每个属性

jes*_*rhh 18 css qt styling qml

我知道QML不像小部件一样支持CSS样式,我已经阅读了关于样式/主题的替代方法:

这些方法的共同点是它们要求开发人员指定可以设置样式的QML部分,方法是绑定到"样式化QML文件/单例"中的属性,或者使用Loader加载不同的QML组件在样式名称上.我想要的是像CSS中的"id"选择器而不是"类"选择器,因此单个QML文件不必知道它们是否将在以后设置样式.

我目前的方法使所有QML文件看起来与此类似(使用链接2中的方法):

Main.qml

Rectangle {
    Id: background
    color: g_theme.background.color 
    //g_theme is defined in root context and loaded dynamically
}
Run Code Online (Sandbox Code Playgroud)

我想做的是:

Main.qml

Rectangle {
    Id: background
    color: “green” // default color
}
Run Code Online (Sandbox Code Playgroud)

然后有一个定义(或类似)的样式文件

Main.qml #background.color: red
Run Code Online (Sandbox Code Playgroud)

目前这是可能的,还是未来Qt版本的管道,或者首选的样式方式是否仍然类似于上面链接中描述的方法?

The*_*roo 13

首选方法是不在默认组件上应用样式,而是从这些组件派生以创建预先设置的自定义组件.

我为我的项目做了什么:

首先,我创建了一个集中的"主题"文件,作为JavaScript共享模块:

// MyTheme.js
.pragma library;
var bgColor   = "steelblue";
var fgColor   = "darkred";
var lineSize  = 2;
var roundness = 6;
Run Code Online (Sandbox Code Playgroud)

接下来,我创建依赖它的自定义组件:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

然后,我可以使用一行代码在任何地方使用我预先设置的组件:

MyRoundedRect { }
Run Code Online (Sandbox Code Playgroud)

这种方法有一个巨大的优势:它真的是面向对象的,而不是简单的皮肤.

如果你想要甚至可以在自定义组件中添加嵌套对象,比如文本,图像,阴影等......甚至是一些UI逻辑,比如鼠标悬停时的颜色变化.

PS:是的,可以使用QML单例代替JS模块,但它需要额外的qmldir文件,并且仅从Qt 5.2支持,这可能是限制性的.显然,上下文属性中的C++ QObject也可以工作(例如,如果你想从磁盘上的文件加载皮肤属性......).