[DTK] 关于DTK的演进,实际上html+CSS等标记语言已经给出最合适的方式
Tofloor
poster avatar
凡
deepin
2023-08-04 03:05
Author

关于DTK,实际上deepin现在正在不断的拓展,寻找更多适合国内应用软件开发编程方式。比如,接近QT模式的DTK Core、DTK Widget、DTK Gui,类似QML的DTK Declarative。

这两种开发模式都有各自优点:
ef561b4a469fb11b8afb999f34aaf0fb.png
1.DTK Core、DTK Widget、DTK Gui,这种类似Qt的套件都是主要有C/C++代码实现,性能很高;

2.类似QML的DTK Declarative,软件窗口界面的排版和编写非常方便,但是运行性能上比DTK Widget差。

那么,能不能折中一下,我们可不可继续对DTK Widget进行封装一下,就是DTK Widget相关组件,可以重新进行封装。

DTK封装的模式,尽量与现在的Html+CSS的规范一致,比如button的事件处理、button的布局样式调整、动画处理等等。


【自定义控件Button-效果展示】

20210327191244244.gif

如上图,鼠标移动到窗口中的Button-Haihong Pros时,Button的框体内从“白”变为“蓝”,button的字体颜色从“蓝”变为“白”。

这种组件的样式变化以及点击事件,都需要对Button进行很好的封装才行。

image.png

image.png

可以看到,Html非常简单在文本中编写出button组件,然后用class标记了button的样式和鼠标点击后的效果,而鼠标实际相关的事件动作内容我们是无法看到的,这说明Html+CSS在底层封装的很好。不像QT现在还要重复调用QMouseEvent,重写相关代码实现事件的处理过程。

也就是说,Html+CSS在底层已经把QMouseEvent相关事件与其进行很好绑定,因为很多点击事件在功能上都是相同的,且执行流程也一致,没必要重复性让程序员再去实现。

从我个人的看法,其意思也非常简单,那就是QT/DTK在进行事件处理时,可以让编程人员不再编写QMouseEvent相关事件内容,而是直接调用组件时就附带有相关事件的处理,如果不能满足自己的需求,可以在封装的代码中继续添加相关内容。

还有一点,那就是CSS相关的样式设置,也可以在其他组件中进行重复利用,这也能减轻软件开发者的工作量


最后,DTK确实正在不断演变、扩充更多开发编程方式,但是关于DTK Core、DTK Widget、DTK Gui的进一步封装还是非常有必要的,如果让编程人员快速上手、快速编译调试等等都是可以改进的最好方式。

(**以上内容,纯属个人观点,本人主要目的是为了减轻DTK/QT的工作量,如果DTK Widget中的组件名都改成HTML中的标记语言属性名也不错,如有异议,可在评论区讨论)

Reply Favorite View the author
All Replies
2 / 2
To page
avatar
ad1998
deepin
2026-08-13 13:30
#21
wlly-lzh:

在下只是好奇要如何进行封装,请阁下封装一部分代码给我们看看。

没有喷哦!

我觉得,直接让dtk 支持css 或者一键 html+js+css 转 dtk 的功能更实用,

Reply View the author
avatar
ad1998
deepin
2026-08-13 13:34
#22

DTK_CSS_架构图.png

DTK CSS 功能开发计划书

版本:v0.1(草案,待确认定稿) · 日期:2026-08-13 流程:先定稿本计划书 → 用户确认 → 按计划进入开发


0. 文档目的

本计划书研究 DTK(Deepin ToolKit)框架的样式体系,提出在其上新增 「DTK CSS」 能力的整体方案:让开发者用接近 Web CSS 的语法为 DTK 应用描述界面样式,由引擎把 CSS 翻译为 DTK 原生的 DPalette / DStyle / DFontSizeManager 以及安全的 QSS 桥接,从而兼顾明暗主题、控件状态与 DTK 视觉规范。


1. 背景与目标

1.1 现状

  • DTK 应用当前做界面样式主要靠 C++ 调用 DPalette / DStyle / DFontSizeManager,或 DTK 5.x 的** QSS .theme 文件**(DThemeManager)。
  • 从 DTK 6.0 起 DThemeManager 已废弃,主题管理并入 dtkgui 的 DGuiApplicationHelper,改为以调色板(palette)为主线。
  • 对熟悉 Web/CSS 的开发者而言,现有方式不够直观,缺少一份「声明式、可复用、可主题化」的样式表。

1.2 目标

  • 提供一套 DTK CSS 语言 + 解析/应用引擎:用 CSS 选择器 + 属性描述样式。

  • 引擎把 CSS 翻译为 DTK 原生样式 API,做到:

    • 主题感知:明暗双调色板,跟随系统/应用主题切换,无需重启;
    • 状态完整:normal / hover / pressed / disabled / focus;
    • 渐进增强:能用原生 DTK API 表达的走原生,表达不了或更适合 QSS 的走 QSS 桥接;
    • 不破坏 DTK:仅做二次样式覆盖,不改动控件绘制逻辑。

1.3 非目标

  • 不重写/替换 DTK 控件绘制(仍由 DStyle / chameleon 负责)。
  • 不替代 QML 的 Palette {} 类型(DTK CSS 以 Widget/C++ 为主,QML 为可选扩展)。

2. DTK 样式体系调研结论

2.1 模块分层

模块 职责 与样式的关系
dtkcommon 构建基础设施(qmake pri/prf) 新模块沿用
dtkcore 非图形能力(系统信息/文件/日志) 无
dtkgui 图形基础(无 UI 控件) DPalette、DGuiApplicationHelper、DColor、DFontSizeManager、DPlatformTheme
dtkwidget QWidget 控件封装 DStyle(继承 QCommonStyle)、DApplication、各 D*控件
dtkdeclarative QML 绑定 可选:Palette {}类型(参考)
qt5integration chameleon 样式插件 D*控件实际由 chameleon 绘制

2.2 关键使能点(为什么 DTK CSS 可行)

DTK 自定义控件由 DStyle/chameleon 自行绘制,并不依赖 QSS 来渲染自身背景。 因此 QSS 可作为「二次样式」安全使用,不会破坏 DTK 视觉规范——这正是 DTK CSS 能落地的底层基础。

2.3 调色板 DPalette

  • 继承 QPalette,新增 DTK 扩展色角色(DPalette::ColorType):

    • 标准角色:Window、WindowText、Base、Text、Button、ButtonText、Highlight、HighlightedText、AlternateBase、PlaceholderText 等;
    • DTK 扩展角色:ItemBackground、TextTitle、TextTips、TextWarning、FrameBorder 等。
  • 颜色分组(QPalette::ColorGroup):Normal/Active、Disabled、Inactive;控件还有 Hover/Pressed/Focus 等由 DStyle 绘制的状态。

2.4 主题与度量

  • DGuiApplicationHelper 用 ColorType(UnknownType=跟随系统 / LightType / DarkType) 管理明暗;切换时发 themeTypeChanged() 信号。

  • DStyle 提供原生度量(部分默认):

    • PM_FrameRadius=8(控件圆角)、PM_TopLevelWindowRadius=18(窗口圆角);
    • PM_ContentsMargins=10、PM_ContentsSpacing=10、PM_FocusBorderWidth=2、PM_ShadowRadius 等。
  • 设置圆角必须用原生 API:DStyle::setFrameRadius(widget, r)(底层写属性 _d_dtk_frameRadius)。QSS 的 border-radius 对 DStyle 自绘背景不生效。


3. 总体设计

3.1 模块定位(推荐)

  • 新建独立模块 dtkcss,与 dtkcommon/dtkgui/dtkwidget 同级,依赖 dtkwidget + dtkgui(QML 绑定可选依赖 dtkdeclarative)。
  • 备选方案:并入 dtkwidget 作为 css 子组件(耦合更紧、升级更慢)。推荐独立模块,便于单独发版与测试。

3.2 设计原则

  1. 主题感知:解析时为每个可着色属性生成 Light/Dark 两套调色板,绑定到控件并监听 themeTypeChanged() 实时切换。
  2. 原生优先:圆角、边距、间距、字号、阴影等走 DStyle/DFontSizeManager 原生 API;颜色走 DPalette 角色覆盖。
  3. QSS 桥接兜底:hover/pressed/focus 伪类、渐变、背景图等 QSS 原生支持且 DTK 允许二次样式的内容,生成 QSS 规则命中对应控件。
  4. 声明式 + 复用:支持 CSS 变量(--var)、@media 明暗主题块、@theme auto/light/dark。

4. CSS 语法规范(草案)

4.1 选择器

  • 控件类选择器:DMainWindow、DButton、DLineEdit、DLabel、DSlider、DSwitchButton …(也兼容 Qt 标准类如 QPushButton,见待确认问题 5)。
  • 通配:*。
  • ID 选择器:#object-name(按 QObject::objectName 命中)。
  • 属性选择器:DLineEdit[warning="true"]。
  • 后代/子代:DMainWindow DButton。

4.2 伪类(状态)

  • :hover、:pressed、:disabled、:focus、:checked(对应控件状态)。
  • 明暗主题用 @media 而不是伪类(见下)。

4.3 主题块



5. 属性映射表(CSS → DTK)

CSS 属性 映射到 适用 备注
background/background-color DPalette角色(Window/Base/Button/ItemBackground,按上下文选) 基础/明暗 生成 Light+Dark 双值
color DPalette文字角色(WindowText/Text/ButtonText) 基础/明暗
border-color DPalette::FrameBorder 基础/明暗
border-width DStyle度量 / QSS 基础
border-radius DStyle::setFrameRadius 基础 必须走原生,QSS 圆角对自绘背景无效
padding/margin PM_ContentsMargins 基础 经 setProperty
spacing PM_ContentsSpacing 基础
font-size DFontSizeManager等级(T1–T10)或 px 基础
box-shadow DStyle阴影度量(PM_ShadowRadius 等) 基础
opacity setWindowOpacity/setOpacity 基础
background-image/ 渐变 QSS 桥接 基础 DTK 原生不表达
:hover/:pressed/:focus QSS 伪类桥接 状态 QSS 原生支持,DTK 允许二次 QSS
:disabled QPalette::Disabled组 状态

6. 架构与核心类

6.1 类设计(命名空间 DTK_CSS_NAMESPACE / DCss)

  • DCssParser:词法 + 语法分析,产出 DCssStylesheet(规则列表)。

  • DCssSelector:把选择器编译为匹配器,对 QWidget 做类/objectName/属性/状态匹配。

  • DCssRule / DCssDeclaration:单条规则与声明(含所属 @media、伪类)。

  • DCssApplicator:核心转换器。对目标控件树:

    1. 生成 Light/Dark 双 DPalette 覆盖,绑定控件并随 themeTypeChanged() 切换;
    2. 写入 DStyle 度量(frameRadius / margins / shadow)→ setProperty / DStyle::setFrameRadius;
    3. 生成 QSS 字符串 承载 hover/pressed/focus 与渐变/图片等,调用 widget->setStyleSheet()(或应用级 QApplication)。
  • DCssApplicationHelper(单例):loadAppCss(path) / loadAppCssString(str)(应用级);registerWidget(w)(主题切换时重算);监听 DGuiApplicationHelper::themeTypeChanged()。

6.2 对外 API(草案)



6.3 数据流


(架构图见对话内联示意)


7. 实现里程碑

阶段 内容 产出
M0 调研 + 本计划书定稿 本文档
M1 模块骨架:dtkcss的 cmake/qmake、pkg-config、DCssApplicationHelper桩、命名空间 可编译空模块
M2 CSS 解析器:tokenizer + parser + AST + 选择器模型 + 单元测试用例 解析库 + 测试
M3 应用器①:DPalette映射(基础色/文字/边框)+ 明暗双调色板 + 主题切换 颜色生效
M4 应用器②:DStyle度量(frameRadius/margins/shadow)+DFontSizeManager 几何/字号生效
M5 应用器③:伪类与 QSS 桥接(:hover/:pressed/:disabled/:focus+ 渐变/图片) 状态/复杂属性生效
M6 应用级加载 API + 示例程序(仿 examples/collections的 demo) 可运行 demo
M7(可选) QML 绑定(dtkdeclarative的 Css附加属性) QML 支持
M8 文档 + 集成/验收测试 交付文档与测试

8. 风险与对策

风险 对策
DTK 自定义控件由 chameleon 自绘,部分属性 QSS 不生效 圆角/边距/阴影等走 DStyle原生 API;仅把 QSS 用于其原生支持且 DTK 允许二次样式的伪类/渐变
DTK 5.x 与 6.x API 差异(DThemeManager6.0 废弃) 以6.x 的 DGuiApplicationHelperpalette 主线实现,必要时对 5.x 做兼容分支
选择器命中精度(objectName / 继承链 / 标准 Qt 类) 明确匹配规则(类全名匹配 + objectName + 属性),并在文档中标注支持范围
大样式表 + 主题切换的重算性能 缓存 AST,仅主题切换时重算调色板,不重新解析

9. 验收标准

  1. 给定一份示例 CSS,能改变 DButton / DLineEdit / DMainWindow 等的基础背景、文字色、圆角、边距。
  2. 切换系统明暗主题时,CSS 中 @media dark 规则自动生效,无需重启应用。
  3. :hover / :pressed 状态视觉变化生效。
  4. 提供 示例程序(demo) 与 单元/集成测试,且测试通过。
  5. (若做 M7)QML 侧 Css 附加属性可达到同等效果。

10. 待确认问题(请确认或调整)大家都来提提意见吧

  1. 模块形态:新建独立模块 dtkcss(推荐)还是并入 dtkwidget?
  2. 目标 DTK 版本:以 DTK 6.x(palette 主线,DThemeManager 已废弃)为准,还是同时兼容 5.x?
  3. 实现策略:混合式(DPalette/DStyle 原生 + QSS 桥接伪类,推荐) vs 纯 QSS 转译 vs 纯原生映射?
  4. 覆盖范围:仅 C++/Widget(推荐先做),还是也要 QML(dtkdeclarative) 绑定(M7)?
  5. 选择器范围:仅 DTK 控件(D*),还是也支持 Qt 标准控件(QPushButton 等)?

以上 5 点确认后,本计划书即定稿,进入 M1 开发。

Reply View the author
2 / 2
To page