[杂项] QSS
前言
经过博主近期一个月在 QML & Quick
方面的预研,部门线上产品已经可以看到 QML
相关内容。现阶段,组内正在使用 QML
开发 IM 需求。
组内技术栈转型是个很大挑战。所以,决定这么做是有前提的:
- 对于博主来说,常规业务开发涉及的 QWidget 相关技术已没有任何挑战性;
- 对新技术的预研,有相当的成果:利用业余时间,博主使用 QML 把 QWidget 相关业务已实现 80%(低代码,且效果更好)。
- 组内成员对
QWidget
掌握程度没那么高,比如:QSS 很容易被滥用。
预备知识
QSS 就是 QWidget 会用到的样式表。只有 QWidget 会用到 QSS 。QML 是脚本语言啦,它依赖 Quick 提供的可视化组件。而 Item 系列的可视化组件是 JSEngine 负责渲染的。所以,QWidget 和 QuickItem 是属于两个完全不想干的领域(QObject 是唯一共性)。
以博主对 QSS 的认识,其大致可分为:
- CSS 部分: 仅限 2.0 版本。QSS 处于维护状态,应该永远支持不了 CSS3 了;
- Subcontrol 部分:QWidget 独有,也是本文介绍的重点;
- QProperty 部分:扩展样式表功能, 以达到出其不意的效果;
技术分析
本节对以上文中的 CSS,Subcontrol 以及 QProperty 部分进行简要介绍。
CSS 部分
CSS 部分就不展开讨论了,也就那么点知识。博主在 DJI 就职时,负责开发的 Electron 桌面客户端涉及到大量的 CSS 技术。
Subcontrol 部分
玩转 QWidget 的重要组成部分。Subcontrol 依赖于 CSS 的 盒模型 ,以控制子控件绘制的位置:Subcontrol-Origin, Subcontrol-position, 以及起到微调作用 Top 和 Left 属性。
- Subcontrol-Origin
subcontrol-origin 定义 children widget 在 parent widget 中绘制的包围盒,默认在 padding 的矩形中绘制。如下:- subcontrol-origin: margin
- subcontrol-origin: border
- subcontrol-origin: padding
- subcontrol-origin: content
- Subcontrol-Position
由 subcontrol-origin 定义了在 parent widget 上的绘制区域后,如:padding 包围区。那这么大的范围,具体绘制在哪里呢? subcontrol-position 进一步限制绘制方向。- subcontrol-origin: left
- subcontrol-origin: right
- subcontrol-origin: center
- subcontrol-origin: top
- subcontrol-origin: bottom
- Top & Left
top 和 left 属性用于微调 subcontrol位置, 比如: 在 ::hover 和 ::pressed 状态时,通过微调达到视觉上的动画效果。
QProperty 部分
一个属性的行为就像一个类的数据成员,它有通过元对象系统访问的附加功能。本文仅介绍 QProperty 在 QSS 方面发挥的作用,也即各种 pseudo-classes,如:enabled, hover, pressed, checked。
但是呢,博主不打算介绍 Qt 在各个 QWidget 派生类中内置的各种状态属性。 本节仅举一例,来凸显 QProperty 在样式表功能扩展方面的能力。
对于 QCheckBox 控件,checked 状态 与 enabled 状态 存在交叉的场景,即:enable 和 disable 状态下,checked 样式需要具有不同的 UI 显示。这个时候,单凭 CSS 提供的能力是比较难办到的。借助于 Property 属性,我们可以通过几行简单的 QSS 语句就能对齐进行区分:
- QSS 配置
1
2QCheckBox::disabled[check=true]{image: "qrc://cat.png"}
QCheckBox::disabled[check=false]{image: "qrc://dog.png"} - Logic 控制
1
2control->setProperty("check", true);
control->style()->polish();
附记
在上文中,我们看到 style()->polish()
语句。本小节就附上一些心得:
- polish: 在程序运行时,QWidget 的样式发生变化需要配合
polish
才能生效; - updateGeometry: 当 QWidget 的 Size,Geometry 相关策略发生变化时,需要配合
updateGeometry
才能生效。比如:sizeHint 变化,maximumHeight 变化等; - update:当 UI 以任何形式变化时,有些情况会存在无法实时刷新,此时就需要配合
update
才能生效。比如:当 hover 状态下,通过修改 style-sheet 方式更改 QPushButton 的背景图片时。