文章目录

  • QStyle
  • DTK Style
    • DStyle
    • DStyleOption
    • DPalette
  • QStyle 和 QPalette 的关系
  • DTK 控件设计
      • Normal
    • Hover
    • Pressed
  • 代码流程描述
  • 字号使用规范
  • 如何实现一个全新的控件
  • 如何自绘控件
  • 如何自定义控件的一些参数
  • 如何添加图标
    • 此规范仅用于约定应用程序中图标的存储和使用,其它图片资源不可使用此规范!
    • icon_demo.zip #示例程序
  • 下载地址:

简 述: DTK 基础知识,尤其使用 DTK 开发应用软件或者参与维护 DTK 库,此都是一个良好的入门级别的知识;且本文档着重讲解 “DTK自定义控件” 的规范。 此处为一个搬运,为了易于搜索和自己做一个记录,收录进自己目录中。

给 DTK 库加了一个基础知识性的 WiKi,里面有一些 DTK 绘画基础知识、绘画原理流程、自定义控件规范、图标的使用。 其由 zccrs 所编写。

QStyle

阅读此文档需要点此先熟悉以下类:

  • QStyle
  • QStyleOption
  • QStylePainter
  • QPalette

DTK Style

DTK Style插件的实现可以划分为两部分:

  • Qt 库的内置控件
  • DTK 自定义控件

本文档着重讲解“DTK自定义控件”的规范。DTK Widget 模块跟控件样式相关的主要有三个类:

  • DStyle
  • DStyleOption
  • DPalette
DStyle

DStyle 继承于 QCommonStyle,在基类(QStyle)的基础上添加了一些枚举值以及绘制、加工类的函数。Qt 所有内置控件均在 paintEvent 中使用 QStyle 中提供的各种 drawXXX 接口进行绘制,另外,QStyle 中定义了大量的枚举类型,如 QStyle::PrimitiveElement、QStyle::ControlElement、QStyle::SubControl 等,这些枚举类型用于控件的绘制、布局、标志位等抽象接口的定义中。QStyle 满足了 Qt 原生控件自定义风格的需求,同理,DStyle 需要在此基础上满足 DTK 控件自定义风格的需求。

DStyleOption

用于扩展 QStyleOption。如 DStyleOptionButton 需要对 QStyleOptionButton 就行扩展,它需要同时继承 DStyleOption 和 QStyleOptionButton。

DPalette

控件的行为虽然不同,但是它们的配色有很多共同的地方,在 Qt 的 GUI 模块中,QPalette 类负责管理所有通用型颜色。每一个 QWidget 对象都有对应的 QPalette,当没有使用 QWidget::setPalette 指定控件使用的调色板时,其将跟随 QApplicatioin::palette。

QPalette 中定义了两个枚举类型:

  • ColorGroup 颜色的分组,包含:Disabled、Active(Normal)、Inactive 三个值
  • ColorRole 颜色的类型,包含:Background、Base、Foreground 等一系列值

我们可以把 ColorRole 定义的颜色理解为 c++ 中的基本数据类型(int double等),则控件的设计类似于 c++ 类的设计,一个是封装基本数据类型定义一个类,另一个则是通过对基础颜色的组合创建一个控件。

QPalette 包含十几种常用的颜色,能满足 Qt 所有内置控件的绘制需要。但是 DTK 控件的设计在配色上更加的丰富,QPalette::ColorRole 中定义的基本颜色无法满足需求,因此在 dtkwidget 库中定义了 DPalette 类,并且添加了 DPalette::ColorType 的枚举类型,用于为 DTK 控件添加基本色的定义。

QStyle 和 QPalette 的关系

QApplication 会在初始化阶段(当使用 QApplication::setStyle 后也会执行以下步骤)调用 QStyle::standardPalette 获取一个标准的 QPalette 对象,这个对象在各个控件的 paintEvent 中被初始化给 QStyleOption (用于存储绘制控件所需要的所有数据),之后在 QStyle 绘制控件时则从 QStyleOption::palette 中获取定义的各种颜色值。对于 QApplication、QStyleOptin、QWidget 而言,它们只识别 QPalette,因此,DPalette 的初始化目前是放置在 QStyle::polish(QApplication*) 中,由 DPalette 自己管理 QApplication 和 QWidget 对象所对应的 DPalette 数据,在 style 插件的实现中则通过 DPalette::get 静态函数获取调色板对象。

DTK 控件设计

在 DDEV20 的设计中,有以下几个特点。首先先看一张图

每个控件分为五个状态:

  • Normal
  • Hover
  • Pressed
  • Disabled
  • Focus

于此相关的是,主窗口层面还分为 Active 和 Inactive 状态,也就是窗口是否被激活的状态。窗口的状态可以和控件状态相互叠加,因此,叠加后的控件状态共有十种组合。不过,在控件中其实不用过于关心窗口的状态,窗口 Active 时控件都是默认样式,Inactive 时则把所有颜色的不透明度降低 40%。同理 Disabled 状态则把所有颜色的不透明度降低 60%。因此,除去这两个特殊状态后,控件中还剩余 Normal Hover Pressed Focus 四个状态需要关心。

Normal

控件默认状态,使用 DPalette 的 Normal 组中各个 ColorRole/ColorType 的定义即可。

Hover

控件的 hover 状态可以由 normal 状态经过颜色变换(调色:如提供颜色亮度等),可使用 DStyle::generatedBrush 获取加工后的颜色值。DStyle 定义了 StyleState 用于指定需要加工的目标颜色类型,默认 Normal 可以不进行任何加工。

Pressed

和 Hover 状态一样,也是由 normal 状态经过颜色变换得到。

代码流程描述

字号使用规范

DFontManager

字号分为十个等级,T1-T10,默认为 T6 级别,当系统中字号大小改变时,所有级别基于默认级别进行同值增减。例如,T6 当前对应的字号为 16px,在控制中心将字号调整为 20px 后,T1-T10 的字号都将增加 4px。所有的控件设计中均不可直接指定字号大小,如果需要对特定的 QWidget 对象设置字号等级,可以使用 DFontSizeManager::bind 接口绑定到对应的级别。

如何实现一个全新的控件

首先为此控件添加需要的枚举值,如 DSuggestButton,QStyle 中已经包含了 QStyle::CE_PushButton 的定义,这部分不用再进行扩展,查看 QStyleOptionButton,它在 ButtonFeatures 中定义了按钮的一些特性,因此我们需要继承 QStyleOptionButton 进行扩展。

class DStyleOptionButton : public QStyleOptionButton, public DStyleOption
{public:enum ButtonFeature {SuggestButton = (CommandLinkButton << 1),WarningButton = (SuggestButton << 1)};void init(QWidget *widget) override;
};

这是 DStyleOptionButton 的代码实现,添加了两个枚举值 SuggestButton、WarningButton。在 DSuggestButton 的 paintEvent 中将使用这些新加的值绘制自定义的按钮。

void DSuggestButton::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)QStylePainter p(this);DStyleOptionButton option;option.features |= DStyleOptionButton::ButtonFeatures(DStyleOptionButton::SuggestButton);initStyleOption(&option);option.init(this);p.drawControl(QStyle::CE_PushButton, option);
}

最终,对 QStylePainter::drawControl 的调用将变为对 QStyle::drawControl 的调用。

XXX::drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *w = nullptr)
{switch(element) {case CE_PushButton:...QStyleOptionButton *opt_button = static_case<QStyleOptionButton*>(opt);if (opt_button->features.testFlag(DStyleOptionButton::SuggestButton)) {// draw suggest button}...break;}
}

这样即完成了对 DSuggestButton 的绘制。

如何自绘控件

有些控件在 Qt 以及 DTK 库中均不存在,在应用程序的开发中需要自己绘制实现,如控制中心个性化模块中的颜色选择控件:

paintEvent 代码:

void paintEvent(QPaintEvent *event)
{QPainter pa(this);QStyleOption opt;opt.initFrom(this);int borderWidth = style()->pixelMetric(DStyle::PM_FocusBorderWidth, &opt, this);int borderSpacing = style()->pixelMetric(DStyle::PM_FocusBorderSpacing, &opt, this);const QMargins margins(borderWidth + borderSpacing, borderWidth + borderSpacing, borderWidth + borderSpacing, borderWidth + borderSpacing);    pa.fillRect(rect().marginRemoved(margins), color); // 填充颜色背景pa.setPen(QPen(borderWidth, opt.palette.highlight())); // 设置边框的宽度和颜色pa.drawEllipse(rect()); // 绘制选中的边框
}

从例子中可以看出,所有和颜色相关的数据均从 QPalette 中读取,所有和大小相关的数据均从 style 对应的接口中读取。

如何自定义控件的一些参数

如更改文本颜色:

QLabel label("test");
QPalette pa = label.palette();
pa.setColor(QPalette::Text, Qt::red);
label.setPalette(pa);

如何添加图标

一个完整的应用程序主题需要关注的不仅仅是控件的样式,有时,程序中对图标的使用也需要区分深色还是浅色。在 Qt 库中,查找和使用图标都可以通过 QIcon 完成,为了方便图标自动跟随程序主题,DDE 桌面环境在 Qt platform theme 主题插件中添加了一个内置的图标主题,路径为:"qrc:/icons/deepin/builtin/[light/dark]",其中,lightdark子目录为可选,它们分别为应用程序提供亮色和暗色图标的存储,如果图标本身为通用型(在任何主题下都可使用),则图标文件直接放置到"qrc:/icons/deepin/builtin"目录即可。

图标分为三种类型:

  • TextType 纯文本性图标,其颜色会跟随画笔的前景色变化(和文字颜色保持一致)。文件放置路径:"qrc:/icons/deepin/builtin/[light/dark]/texts"
  • ActionType 动作型图标,其颜色会在其 Mode 改变时跟随画笔前景色(Normal模式图标颜色不会发生变化)。文件放置路径:"qrc:/icons/deepin/builtin/[light/dark]/actions"
  • IconType 图标型图标,其颜色在任何模式下都不会变化。文件放置路径:"qrc:/icons/deepin/builtin/[light/dark]/icons"

图标名称规范:

名称前面需要添加能标示当前程序的前缀,例如控制中心的图标文件 dcc_xxx_32px.svg(设计大小为32)每一个都会有 “dcc_” 的前缀,其后跟图标s名称(图标名称单词间使用 “_” 符号链接,且全部使用小写字母),再接着,"_32px" 为图标大小标识,标识此图标默认大小,最后的 “.svg” 为图标文件后缀名。

后记:

qrc 表示是一个 Qt 资源文件,此文件需要应用程序中自行创建。"/icons/deepin/builtin" 为路径的固定前缀,随后的目录则为三种类型主题对应的目录。“actions” 为图标的类型目录,目前支持 “texts”、“actions” 和 “icons” 三种类型,“texts” 和 “actions” 目录用于放置一些工具性图标(一般都比较小,且颜色单一),“icons” 则用于放置一些颜色丰富的图标。

添加图标文件后,在程序中只需要使用 QIcon::fromTheme(“dcc_xxx”) 即可获取当前主题对应的图标对象,“dcc_xxx” 为图标文件名称,不包含图标大小标识和文件后缀名!

此规范仅用于约定应用程序中图标的存储和使用,其它图片资源不可使用此规范!

icon_demo.zip #示例程序

下载地址:

QtExamples

欢迎 starfork 这个系列的 QT / DTK 学习,附学习由浅入深的目录。

DTK 基础教程:自定义控件规范相关推荐

  1. 枚举命名规范_UE4 C++基础教程 - 编码规范

    为什么要学习编码规范? 良好的编码规范不仅利于项目维护,也增加了代码辨识度.使我们在阅读代码时能够更加清晰的理解代码意图.维护编码规范不是一件机械化的工作,它更像是一门艺术,让我们在有限的规范内发挥自 ...

  2. Spring Boot 2.x基础教程:Swagger静态API文档的生成

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 翟永超 来源 | didispace.com/spring-boot-learni ...

  3. Spring Boot 2.x基础教程:JSR-303实现请求参数校验

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 翟永超 来源 | didispace.com/spring-boot-learni ...

  4. python基础教程书籍推荐-小猿圈推荐Python入门书籍,不知道这些你就太low了。

    原标题:小猿圈推荐Python入门书籍,不知道这些你就太low了. PYPL发布6月编程语言排行榜,盘踞前五名的分别是Python.Java.Java.C# 和 PHP.近五年,Python采用率高居 ...

  5. python基础教程是什么意思-python基础教程都有什么?

    分享一下传智播客的python基础教程 第一阶段 Python核心编程 可掌握的核心能力 1.掌握Python基础语法,具备基础的编程能力; 2.建立起编程思维以及面向对象程序设计思想.解决的现实问题 ...

  6. Web前端-JavaScript基础教程上

    Web前端-JavaScript基础教程 将放入菜单栏中,便于阅读! JavaScript是web前端开发的编程语言,大多数网站都使用到了JavaScript,所以我们要进行学习,JavaScript ...

  7. Python基础教程(十):CGI编程、MySQL数据库

    Python CGI编程 什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如: ...

  8. 变量命名规则_JavaScript基础教程(二)变量、常量与运算符

    常量变量与运算符 从本次课程开始我们将进入JavaScript基础教程学习,本课程附带PPT讲义,课程主要针对JavaScript学习入门者. 变量 在计算机程序设计语言中,变量是存储数据的容器,变量 ...

  9. 图书推荐:《ASP.NET.基础教程——C#案例版》

    本书结合用C#语言编写的可实际运行的示例代码,讨论了ASP.NET的构架.Web窗体.配置.HTTP管道.故障诊断和错误处理.验证.数据绑定.自定义控件.缓存.状态管理和安全性,阐述用C#构建基于We ...

最新文章

  1. Servlet 服务器端小程序
  2. 硅谷产品实战-总结:23、增长的核心在于减少用户阻力
  3. Self-Tuning Spectral Clustering论文阅读和代码理解
  4. cmd管道无法接收特定程序返回值_渗透不会反弹shell?来教你写一个cmd的shell
  5. 自定义smokeping告警(邮件+短信)
  6. ASP.NET Core 导入导出Excel xlsx 文件
  7. Mysql入门的10条语句
  8. Kubernetes 版本锁定到1.12.3
  9. CentOS 6.6 搭建Zabbix 3.0.3 过程
  10. 【clickhouse】docker 下 搭建 clickhouse 监控
  11. Ensemble Learning
  12. Apizza 升级了,更好的 api 接口管理和文档编写,欢迎大家访问吐槽!!
  13. Windows系统下快速安装、配置Aira2,及图形界面配置、度盘、B站视频下载
  14. 2015.3.12Arinc424 Tools中SiniArincCls.csParserFile(string sFile)函数正则表达式理解
  15. 2019最佳硬盘:台式机和笔记本电脑的顶级硬盘
  16. 写了个自动批改小孩作业的代码
  17. NTP时间戳和UTC时间戳互转及其原理
  18. Windows10聚焦背景纯灰色
  19. springboot高校社团管理系统
  20. LeetCode 1011. Capacity To Ship Packages Within D Days(python)

热门文章

  1. SQLSTATE 问题分析及解决·第四话
  2. Bulma 使图片居中
  3. 支持向量机详解及代码(SMO算法)
  4. Python将一个负数(int)转换为字节表示的s16
  5. 【Unity3d学习】AR技术的简单了解
  6. 鸟哥笔记|运营超级用户是要激发用户的高裂变能力!
  7. 新功能|新主播|土豆配音全新体验助你芜湖~起飞
  8. Selenium—八种元素定位方法
  9. python 爬取公开IP代理
  10. 简单说一下servlet的生命周期?