[杂项] 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
    2
    QCheckBox::disabled[check=true]{image: "qrc://cat.png"}
    QCheckBox::disabled[check=false]{image: "qrc://dog.png"}
  • Logic 控制
    1
    2
    control->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 的背景图片时。

[杂项] QSS
https://jalencui.com/2023/04/25/QWidget-QSS-Overview/
Author
Jalen Cui
Posted on
April 25, 2023
Licensed under