跳转至

§5.1 颜色格式及其转换

字数 1593 个   代码 21 行   图片 2 张   阅读时间 6 分钟   访问量

一、颜色格式

1.1 tkinter 的颜色

tkinter 仅支持颜色名称字符串和像 #RGB 格式的十六进制颜色字符串(如 #RGB 和 #RRGGBB),此处的 R 表示红色的比例(Red),G 表示绿色的比例(Green),B 表示蓝色的比例(Blue)。

下面举例一些 tkinter 能够识别的颜色字符串:

  • "royalblue"
  • "pink"
  • "#123"
  • "#FF6600"

关于 RGB 颜色格式的其它详细信息,这里不想再额外说明,如果想知道,请自行在别处搜索。

温馨提示:空字符串在 tkinter 中表示没有颜色

空字符串 ""tkinter 中也是可以解析的,表示没有颜色,你也可以将其视为完全透明。在某些情况下这会很有用,比如在 Canvas 中,有些 Item 的边框是有默认颜色的(一般是黑色),如果不想让它们显示出来,就将对应的参数设置为空字符串,这样就变成“透明”了。

1.2 maliang 的颜色

maliang 并没有在接口上对 tkinter 做什么修改,只是增加了一些用于颜色的函数方便开发而已。也就是说,maliang 所有涉及到颜色的地方也是用和 tkinter 一样的颜色字符串的方式来传入颜色的。

猜你想问:Python 已内置了模块 colorsys 来提供颜色相关的函数,为什么 maliang 还专门对此有新的内容?

很简单,colorsys 提供的功能很有限,很多轮子都没有,需要自己造。而 maliang 的子包 maliang.color 提供了更多处理颜色的功能。不过要注意的是,colorsys 提供的接口与 maliang 的不一样,不能混用!

虽然在格式上来说,都是颜色字符串,但实际上 maliang 还实验性地支持 #RRGGBBAA 格式的颜色字符串,但这个功能实现的是“伪 RGBA”,只能完成非常有限的功能。

首先,RGBA 中的 A 表示的是透明度(Alpha),与 R、G 和 B 一样,范围是 0~F,F 表示不透明,0 表示完全透明。但是 maliang 提供的 RGBA 并没有真正意义上实现透明度功能,它只是相对于 Canvas 的背景色做了一定处理的颜色而已。限于技术原因,没办法以低性能开销地方式实现真正的透明度功能。下文会对此作详细的介绍。

二、颜色间转换

2.1 颜色“标识符”

这里所说的“标识符”是 maliang 对一种涉及到的颜色格式的称呼,并非一个类或者常量。maliang 支持处理的颜色“标识符”有下面六种:

  1. rgb: RGB 三元组,例如 (12, 34, 56)
  2. hsl: HSL 三元组,例如 (math.pi, 0.5, 0.5)
  3. hex: 十六进制颜色字符串,例如 "#ABCDEF" 或者 "#12345678"
  4. name: 颜色名称字符串,例如 "royalblue"
  5. rgba: RGBA 四元组,例如 (12, 34, 56, 78)
  6. str: hex(不含八位长度 RGBA 格式的 hex)或 name

其中三位长度与六位长度的 hex 格式和 name 格式可以直接被 tkinter 识别。因此一般情况下,转换后的最终的结果都是这两种格式。虽然这两种可以被直接识别,但并不利于处理,常用的实际上是 rgb 或者其它的格式。这里注意一下,八位长度的 hex 格式的颜色字符串(如 "#12345678")是 maliang 中的“伪 RGBA” 格式,这种是不能被 tkinter 直接识别的,但可以被 maliang 所识别。

关于“伪 RGBA”,假设 Canvas 的背景色是白色,设置的“伪 RGBA”值为 "#FF000078",那么实际呈现的颜色为 "#780000",读者见下面的示例:

import maliang

root = maliang.Tk()
canvas = maliang.Canvas()
canvas.place(width=1280, height=720)

maliang.Label(canvas, (20, 20), text="Label RGBA 0%").style.set(bg="#FF000000")
maliang.Label(canvas, (20, 80), text="Label RGBA 50%").style.set(bg="#FF00007F")
maliang.Label(canvas, (20, 140), text="Label RGBA 100%").style.set(bg="#FF0000FF")
maliang.Label(canvas, (20, 200), text="Label RGB").style.set(bg="#FF0000")

maliang.Label(canvas, (300, 100), text="Label RGBA").style.set(bg="#FF00007F")
maliang.Label(canvas, (320, 120), text="Label RGBA").style.set(bg="#FF00007F")

root.mainloop()

其效果如下:

图1 “伪 RGBA”

很明显,Alpha 设置的值越小,就越透明(和 Tk.alpha 类似)。但多个控件叠加的时候效果并不会像预期的那样,这也是这项功能被称为“伪 RGBA” 的原因。

猜你想问:既然是“伪 RGBA”,那我提前计算出这个 RGBA 的值再设置到控件的样式上不是一样的效果吗?

其实不一样的,写成 RGBA 的格式会好一些。虽然这是“伪 RGBA”,但首先它不需要我们手动去计算,可以减少开发时间;此外,也是最重要的一点,它是动态响应系统主题的!你可以尝试运行上面的代码,然后切换系统的主题,看看这个假的是半透明会不会跟着变化。

当然,能看到变化的前提是,你当前的环境支持跟随系统主题切换程序主题。

2.2 格式间转换

虽然上面涉及到的颜色格式很多,但记住它们在 maliang 的“标识符”就能很容易使用这些转换函数了,下面是它们之间的转换函数:

rgb hsl hex name rgba
rgb \ rgb_to_hsl rgb_to_hex rgb_to_name
hsl hsl_to_rgb \ hsl_to_hex
hex hex_to_rgb hex_to_hsl \ hex_to_name hex_to_rgba
name name_to_rgb name_to_hex \
rgba rgba_to_hex \
str str_to_rgb

具体转换函数的使用方式,可以点击上表中对应函数的文档链接来查看。

温馨提示:颜色转换函数可以使用简化名称来调用

尽管各种颜色格式已经使用“标识符”来简化了,但转换函数的名称仍然比较长,所以 maliang 还为每个转换函数提供了简化的别名,具体来说就是将转换函数中的 “_to_” 给简化为 “2”。举个例子,str_to_rgb 等价于 str2rgb

下面是一个简单使用颜色转换函数的例子(运行结果为文档构建时计算得到):

1
2
3
4
5
6
import maliang.color.convert

print(maliang.color.convert.str_to_rgb("red"))
print(maliang.color.convert.str2rgb("Red"))
print(maliang.color.convert.str_to_rgb("#FF0000"))
print(maliang.color.convert.str2rgb("#F00"))
1
2
3
4
(255, 0, 0)
(255, 0, 0)
(255, 0, 0)
(255, 0, 0)

很显然,上面四个的结果是一致的。这里需要注意的一点就是,颜色名称字符串是不区分大小写的。

如果想知道有哪些颜色名称字符串可以被 tkinter 直接识别,可以在 colortable.MAPPING_TABLE 中找到。它是一个常量字典,记录了所有 tkinter 可以识别的颜色名称字符串及其对应的 RGB 三元组的值。