engines · 绘制引擎层入口
tkdeft 绘制引擎层入口。
本包把"画什么"(声明式规格)与"用什么画"(引擎)分开:
- 规格与引擎基类在 :mod:
tkdeft.engines.base; - 图片缓存在 :mod:
tkdeft.engines.cache; - 颜色解析在 :mod:
tkdeft.engines.colors; - 三个进程内栅格引擎分别在 :mod:
tkdeft.engines.skia_engine/ :mod:tkdeft.engines.pillow_engine/ :mod:tkdeft.engines.cairo_engine。
这个模块只做一件事:把常用接口汇总到一个命名空间里。
内置引擎
====== ====== ========== ==============================================
编号 名字 类型 说明
====== ====== ========== ==============================================
0 tksvg SVG(文件) 默认,保持既有行为完全不变
1 wand SVG(文件) 经 Wand(ImageMagick) 转 PNG,兼容旧 renderer=1
2 skia 栅格 skia-python,质量与速度最好
3 pillow 栅格 Pillow 超采样,零额外依赖,永远可用
4 cairo 栅格 pycairo
====== ====== ========== ==============================================
快速上手
::
from tkdeft.engines import RoundRectSpec, render_roundrect, set_engine
set_engine("skia") # 或 set_engine(2)
photo = render_roundrect(spec, master=canvas) # -> PhotoImage | None
render_* 返回 None 表示"当前引擎不参与这条路径"(SVG 引擎就是如此),
调用方应回退到既有的 svgwrite + tksvg 实现。这样 SVG 引擎与栅格引擎可以共存于
同一套组件代码。
注册表与诊断
::
from tkdeft.engines import list_engines, describe_engines, available_engines
list_engines() # {'tksvg': True, 'wand': True, 'skia': True, ...}
available_engines() # ['tksvg', 'wand', 'skia', 'pillow', 'cairo']
describe_engines() # 带编号/依赖/描述的完整表格,适合打印或喂给 CLI
缓存
::
from tkdeft.engines import cache_stats, set_cache_budget, clear_cache
cache_stats() # {'entries': .., 'hits': .., 'hit_rate': ..}
set_cache_budget(16_000_000) # 调大像素预算(默认 8M 像素)
DrawEngine
绘制引擎基类。
子类需要声明 :attr:name / :attr:kind,并实现 :meth:render_roundrect
等渲染方法:kind == "raster" 的引擎会被画布用作快速路径。
:param str name: 引擎名(注册表里的主键,小写)
:param str kind: "svg" 或 "raster"
:param tuple requires: 依赖的 Python 模块名,供 :meth:available 惰性探测
:param str description: 人类可读的一句话说明
源代码位于: tkdeft\engines\base.py
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | |
index
property
兼容历史 API 的编号(tksvg=0 … cairo=4);不在表里时为 -1。
is_raster
property
是否是进程内栅格引擎(只有它会参与画布快速路径)。
available()
依赖是否都能导入。
:returns: 全部依赖可导入时为 True;不装 skia-python 也不影响
其它引擎(只有 :meth:available 为 False 的引擎不能选)。
源代码位于: tkdeft\engines\base.py
365 366 367 368 369 370 371 372 373 374 375 376 | |
close()
释放引擎持有的资源(可选的钩子,默认什么都不做)。
源代码位于: tkdeft\engines\base.py
422 423 | |
info()
引擎的结构化信息,供 CLI / 文档 / 诊断使用。
源代码位于: tkdeft\engines\base.py
426 427 428 429 430 431 432 433 434 435 | |
render(spec)
按规格自身的类型分发到对应的 render_* 方法。
这是一个便捷入口,等价于 engine.render_roundrect(spec) 之类,
但调用方不需要知道规格的具体类型。
源代码位于: tkdeft\engines\base.py
409 410 411 412 413 414 415 416 417 418 419 420 | |
render_roundrect(spec)
渲染圆角矩形,返回 PIL.Image.Image(RGBA)。
:raises NotImplementedError: 该引擎不支持这条快速路径 (SVG 引擎会走既有的 svgwrite + tksvg 流程)。
源代码位于: tkdeft\engines\base.py
393 394 395 396 397 398 399 | |
render_thumb(spec)
渲染滑块把手,返回 PIL.Image.Image(RGBA)。
源代码位于: tkdeft\engines\base.py
405 406 407 | |
render_track(spec)
渲染滑块进度条槽,返回 PIL.Image.Image(RGBA)。
源代码位于: tkdeft\engines\base.py
401 402 403 | |
supports(kind)
是否支持某类图元("roundrect" / "track" / "thumb")。
源代码位于: tkdeft\engines\base.py
383 384 385 | |
ImageCache
单个 Tk 解释器对应的绘制结果缓存。
键是 (引擎名, 图元类型, spec);值是 (PhotoImage, 像素数)。
所有方法都是线程安全的(由模块级锁保护),可以直接在多线程里查询统计。
:param budget: 像素预算;超出后新规格不再写入缓存(见模块文档里的说明)
源代码位于: tkdeft\engines\cache.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | |
budget
property
writable
像素预算。
pixels
property
当前缓存占用的像素数。
clear()
清空缓存并返回被清掉的条目数。
.. warning::
已经发出去的 :class:~tkinter.PhotoImage 仍然由调用方(画布)持有,
因此清空缓存不会让画面立刻变空白;真正的风险在于之后画布重新引用
同一规格时会重新渲染。
源代码位于: tkdeft\engines\cache.py
105 106 107 108 109 110 111 112 113 114 115 116 | |
get(key)
取缓存图片;未命中返回 None(同时累计命中率统计)。
源代码位于: tkdeft\engines\cache.py
70 71 72 73 74 75 76 77 78 | |
put(key, photo, pixels)
写入缓存;超出预算时 静默放弃(已发出的图片保持有效)。
:param key: (引擎名, 图元类型, spec)
:param photo: tkinter.PhotoImage
:param pixels: 该图片占用的像素数(用于预算核算)
:returns: 是否真的写入了缓存;False 表示这次只能"每次重新渲染"
源代码位于: tkdeft\engines\cache.py
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | |
reset_stats()
把命中/未命中/溢出计数清零(不动缓存内容)。
源代码位于: tkdeft\engines\cache.py
145 146 147 | |
stats()
这条缓存的统计信息(条目数、像素占用、命中率、溢出次数)。
源代码位于: tkdeft\engines\cache.py
132 133 134 135 136 137 138 139 140 141 142 143 | |
RoundRectSpec
dataclass
Bases: _Spec
一个圆角矩形(可带纯色/渐变描边)的完整描述。
坐标系以自身左上角为 (0, 0);width / height 是位图尺寸,
不是坐标对——需要坐标时用 :meth:from_box。
:param width: 位图宽度(像素)
:param height: 位图高度(像素)
:param rx: 圆角半径(x 方向)
:param ry: 圆角半径(y 方向);None 表示与 rx 相同
:param fill: 填充色;None / "transparent" 表示不填充
:param fill_opacity: 填充透明度,0–1
:param outline: 描边色;None 表示不描边
:param outline_opacity: 描边透明度
:param outline2: 渐变描边的第二个颜色;为空则用纯色描边
:param outline2_opacity: 渐变描边第二个颜色的透明度
:param outline_width: 描边宽度(描边居中,几何会自动内缩半个线宽)
:param gradient_stop1: 渐变第一个 stop 的位置(0–1)
:param gradient_stop2: 渐变第二个 stop 的位置(0–1)
源代码位于: tkdeft\engines\base.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
effective_ry
property
实际生效的 y 方向圆角半径(ry 为空时取 rx)。
from_box(x1, y1, x2, y2, radius=0, radiusy=None, **kwargs)
classmethod
按 (x1, y1)-(x2, y2) 的坐标对构造规格。
这是给画布类 API 用的便捷入口:画布上的控件习惯用"两个角"描述矩形, 而规格本身只关心位图尺寸。
:returns: 新的 :class:RoundRectSpec;radiusy 为空时保持 None
(由 :attr:effective_ry 回退到 rx)。
源代码位于: tkdeft\engines\base.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
SvgEngine
Bases: DrawEngine
SVG 系引擎的占位实现。
它们不参与栅格快速路径——真正的绘制仍由各组件里既有的 Flu*Draw 代码
完成,这里只用于在注册表里表达"当前选中的是哪个引擎"。
源代码位于: tkdeft\engines\base.py
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | |
supports(kind)
SVG 引擎不参与栅格快速路径,因此对任何图元都返回 False。
源代码位于: tkdeft\engines\base.py
458 459 460 | |
ThumbSpec
dataclass
Bases: _Spec
滑块的圆形把手:外圈渐变伪阴影 + 外填充 + 内填充。
:param width: 位图宽度(通常等于把手直径 + 阴影余量)
:param height: 位图高度
:param r1: 外圆半径(伪阴影所在的那一圈)
:param r2: 内圆半径
:param fill: 外填充色(画在 r1 - 1 的圆里)
:param fill_opacity: 外填充透明度
:param outline: 伪阴影渐变的第一个颜色
:param outline_opacity: 伪阴影第一个颜色的透明度
:param outline2: 伪阴影渐变的第二个颜色
:param outline2_opacity: 伪阴影第二个颜色的透明度
:param inner_fill: 内圆填充色
:param inner_fill_opacity: 内圆填充透明度
源代码位于: tkdeft\engines\base.py
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | |
from_box(x1, y1, width, height, r1, r2, **kwargs)
classmethod
按画布坐标构造规格(x1 / y1 只影响摆放,不影响位图内容)。
源代码位于: tkdeft\engines\base.py
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | |
TksvgEngine
Bases: SvgEngine
svgwrite 生成 SVG → tksvg 栅格化(默认引擎,保持历史行为)。
源代码位于: tkdeft\engines\__init__.py
150 151 152 153 154 155 | |
TrackSpec
dataclass
Bases: _Spec
滑块的进度条槽:左半段(已选中)+ 右半段(未选中)两个圆角矩形。
:param width: 位图宽度
:param height: 位图高度
:param width2: 左半段(选中部分)的宽度,会被夹到 0..width
:param radius: 圆角半径
:param track_fill: 选中部分的颜色
:param track_opacity: 选中部分的透明度
:param rail_fill: 未选中底轨的颜色
:param rail_opacity: 未选中底轨的透明度
源代码位于: tkdeft\engines\base.py
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | |
from_box(x1, y1, width, height, width2, **kwargs)
classmethod
按画布坐标构造规格(x1 / y1 只影响摆放,不影响位图内容)。
源代码位于: tkdeft\engines\base.py
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | |
UnknownEngineError
Bases: ValueError
请求了注册表里不存在的绘制引擎。
继承自 :class:ValueError,因此历史代码里的 except ValueError 依旧有效。
源代码位于: tkdeft\engines\base.py
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | |
WandEngine
Bases: SvgEngine
svgwrite 生成 SVG → Wand(ImageMagick) 转 PNG(历史 renderer=1)。
源代码位于: tkdeft\engines\__init__.py
158 159 160 161 162 163 | |
available_engines()
当前环境里真正能用的引擎名列表。
源代码位于: tkdeft\engines\base.py
531 532 533 | |
cache_stats(master=None)
缓存统计,便于性能诊断。
:param master: 只看某个解释器;None 表示汇总所有解释器
(额外带一个 interpreters 字段)
::
>>> cache_stats()
{'interpreters': 1, 'entries': 62, 'pixels': 169244, 'budget': 8000000,
'hits': 178, 'misses': 99, 'hit_rate': 0.642, 'overflow': 0}
源代码位于: tkdeft\engines\cache.py
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | |
clear_cache(master=None)
清空缓存,返回被清掉的条目数。
:param master: 只清某个解释器的缓存;None 表示清空全部解释器
.. warning:: 清空后,仍然存在于画布上的 item 会因为图片被回收而变空白。 仅在确实要重建整个界面时调用。
源代码位于: tkdeft\engines\cache.py
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |
clear_engine_error()
清掉失败记录,并允许下次失败时重新发出一次警告。
源代码位于: tkdeft\engines\__init__.py
194 195 196 197 198 | |
describe_engines()
所有引擎的结构化信息列表(按编号排序,含别名与"是否当前")。
与 :func:list_engines 相比,这里的信息更适合直接打印或喂给 CLI/文档。
源代码位于: tkdeft\engines\base.py
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 | |
engine_from_index(index)
把历史编号翻译成引擎名。
:raises UnknownEngineError: 编号不在 :data:RENDERER_INDEX 里
源代码位于: tkdeft\engines\base.py
550 551 552 553 554 555 556 557 558 | |
engine_index(name=None)
取引擎对应的历史编号;None 表示当前引擎。
:raises UnknownEngineError: 引擎不存在
:returns: 0–4;自定义引擎不在 :data:RENDERER_INDEX 里时返回 -1
源代码位于: tkdeft\engines\base.py
541 542 543 544 545 546 547 | |
engine_names()
注册表里的全部引擎名(不过滤可用性)。
源代码位于: tkdeft\engines\base.py
536 537 538 | |
get_cache(master)
取(必要时创建)某个 Tk 解释器对应的缓存。
:param master: 任意 Tk 控件,或 tkapp 本身
:returns: 绑定到该解释器的 :class:ImageCache
源代码位于: tkdeft\engines\cache.py
196 197 198 199 200 201 202 | |
get_engine(name=None, *, strict=True)
取引擎实例。
:param name: 引擎名(大小写不敏感,可以是别名);None 表示当前引擎
:param strict: 名字未知时抛 :class:UnknownEngineError(默认);
置 False 则退回当前引擎,兼容历史行为
:raises UnknownEngineError: strict=True 且名字未知
源代码位于: tkdeft\engines\base.py
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | |
get_engine_name()
当前引擎的名字(比编号直观)。
源代码位于: tkdeft\engines\base.py
604 605 606 | |
last_engine_error()
最近一次渲染失败的原因;一切正常时返回 None。
比直接读 :data:engine_error 更明确,也不会让静态检查器以为你在读、
写一个普通全局变量。
源代码位于: tkdeft\engines\__init__.py
185 186 187 188 189 190 191 | |
lerp_rgba(c1, c2, t)
在两个 RGBA 之间线性插值(t 会被裁剪到 [0, 1])。
:param c1: 起点颜色(t <= 0 时原样返回)
:param c2: 终点颜色(t >= 1 时原样返回)
:param t: 插值位置
源代码位于: tkdeft\engines\colors.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 | |
list_engines()
返回 {引擎名: 是否可用}(只列主名,不含别名,按编号排序)。
::
>>> list_engines()
{'tksvg': True, 'wand': True, 'skia': True, 'pillow': True, 'cairo': True}
源代码位于: tkdeft\engines\base.py
519 520 521 522 523 524 525 526 527 528 | |
normalize_hex(value)
把 #FFF / #FFFFFF 统一成小写 6 位形式(不含 alpha)。
:param value: 形如 "#fff" / "FFF" / "#F0F0F0" 的字符串
:returns: "#rrggbb";超过 6 位的部分(alpha)会被截掉
源代码位于: tkdeft\engines\colors.py
45 46 47 48 49 50 51 52 53 54 | |
parse_color(value, opacity=1.0)
解析颜色 + 透明度。
:param value: 颜色写法(见模块文档);None / "transparent" 表示不绘制
:param opacity: 外层透明度,会与颜色自带的 alpha 相乘(元组色与
#RRGGBBAA 都适用)
:returns: (r, g, b, a);当颜色表示"不绘制"、解析失败或最终 alpha 为 0 时
返回 None,调用方据此完全跳过这一层的绘制
::
parse_color("#ffffff", 0.2) # (255, 255, 255, 51)
parse_color((0, 0, 0, 128)) # (0, 0, 0, 128)
parse_color("transparent") # None
源代码位于: tkdeft\engines\colors.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
parse_opacity(value, default=1.0)
把透明度统一成 [0, 1] 的 float。
:param value: float / int / 数字字符串;None 表示用 default
:param default: 解析失败(或 None)时的回退值
:returns: 夹到 [0, 1] 的浮点数;NaN 与非法值都回退到 default
源代码位于: tkdeft\engines\colors.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
register_engine(engine, *, aliases=(), default=False)
把一个引擎实例登记进注册表。
:param engine: 引擎实例
:param aliases: 额外的别名(例如 ("2",) 让 set_engine(2) 也能命中),
大小写不敏感
:param default: 是否同时把它设为当前引擎;注册表为空时也会自动成为当前引擎
:returns: 传入的 engine,方便写成 register_engine(MyEngine(), aliases=...)
重复注册同名引擎会覆盖旧的实例(便于测试里替换引擎)。
源代码位于: tkdeft\engines\base.py
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | |
render(spec, master)
渲染任意一种绘制规格,按规格类型自动分发。
:param spec: :class:~tkdeft.engines.base.RoundRectSpec /
:class:~tkdeft.engines.base.TrackSpec /
:class:~tkdeft.engines.base.ThumbSpec
:param master: 目标 Tk 控件
:returns: PhotoImage;当前引擎不支持时返回 None
::
photo = render(RoundRectSpec(width=120, height=32, rx=6), master=canvas)
源代码位于: tkdeft\engines\__init__.py
266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
render_roundrect(spec, master)
渲染圆角矩形;当前引擎不支持时返回 None。
源代码位于: tkdeft\engines\__init__.py
282 283 284 | |
render_thumb(spec, master)
渲染滑块把手;当前引擎不支持时返回 None。
源代码位于: tkdeft\engines\__init__.py
292 293 294 | |
render_track(spec, master)
渲染滑块进度条槽;当前引擎不支持时返回 None。
源代码位于: tkdeft\engines\__init__.py
287 288 289 | |
reset_engine()
把当前引擎恢复为出厂默认(tksvg),返回该引擎。
源代码位于: tkdeft\engines\base.py
651 652 653 | |
set_cache_budget(pixels)
设置像素预算,并立即应用到所有已存在的解释器缓存。
:param pixels: 预算(像素数);None 表示恢复默认
:data:DEFAULT_PIXEL_BUDGET(注意:并不是"不限制")
源代码位于: tkdeft\engines\cache.py
222 223 224 225 226 227 228 229 230 231 232 | |
set_engine(name)
切换当前引擎。
name 可以是引擎名("skia" / "pillow" / "tksvg" / "cairo"
/ "wand"),也可以是兼容旧 API 的整数编号:
===== ========== ========================================================== 编号 引擎 说明 ===== ========== ========================================================== 0 tksvg SVG 文件(默认,保持既有行为) 1 wand SVG → PNG(ImageMagick) 2 skia 进程内栅格,速度与画质最好 3 pillow 进程内栅格,零额外依赖,永远可用 4 cairo 进程内栅格(pycairo) ===== ========== ==========================================================
:raises UnknownEngineError: 引擎名/编号不在注册表里 :raises ValueError: 引擎存在但依赖缺失(报错会说明缺哪个包)
非法或不可用的引擎都会抛异常,避免静默降级导致"以为开了 skia 其实还在走慢路径"。
源代码位于: tkdeft\engines\base.py
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | |
to_photoimage(image, master)
PIL.Image → tkinter 的 PhotoImage。
:param image: PIL.Image.Image(RGBA)
:param master: 目标 Tk 控件;必须传,否则图片会挂到默认根窗口,
多 Tk 解释器场景下会出问题
:returns: :class:tkinter.PhotoImage
源代码位于: tkdeft\engines\__init__.py
221 222 223 224 225 226 227 228 229 230 231 232 233 | |
unregister_engine(name)
从注册表里移除一个引擎(连同它的别名)。
:returns: 是否真的移除了。移除当前引擎时,当前选择会回退到默认引擎 (默认引擎也没了就退到剩下的第一个)。
源代码位于: tkdeft\engines\base.py
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | |