engines.base · 引擎基类与规格
tkdeft 绘制引擎抽象层。
本模块是 tkdeft.engines 的"零件库":绘制规格(画什么)与
绘制引擎(用什么画)都在这里定义,注册表也在这里维护。
设计目标
把"画什么"(声明式 spec)与"用什么画"(引擎)彻底解耦:
- 过去:每个组件在
Flu*Draw里各自拼 svgwrite 对象 → 落盘 → tksvg 解析文件, 导致每次 hover/按压都要走一遍磁盘 I/O + XML 解析,单帧 ~5ms。 - 现在:组件构造一个不可变的 :class:
RoundRectSpec,交给当前引擎。 栅格引擎(skia / pillow / cairo)进程内直接出位图,不碰磁盘; SVG 引擎(tksvg / wand)保持原有行为,向后兼容。
三种图元
=============== ==========================================================
规格 说明
=============== ==========================================================
:class:RoundRectSpec 圆角矩形(可带纯色/渐变描边),按钮、面板、输入框都用它
:class:TrackSpec 滑块/滚动条的进度条槽(左选中 + 右底轨)
:class:ThumbSpec 滑块/滚动条的圆形把手(外圈伪阴影 + 两层填充)
=============== ==========================================================
用法速览
::
from tkdeft.engines import RoundRectSpec, set_engine, render_roundrect
set_engine("skia") # 0=tksvg 1=wand 2=skia 3=pillow 4=cairo
spec = RoundRectSpec(width=120, height=32, rx=6, fill="#ffffff")
photo = render_roundrect(spec, master=canvas) # -> PhotoImage | None
对本模块只暴露三件事:规格、引擎基类、引擎注册表。
具体渲染入口见 :mod:tkdeft.engines。
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 | |
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 | |
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 | |
available_engines()
当前环境里真正能用的引擎名列表。
源代码位于: tkdeft\engines\base.py
531 532 533 | |
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_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 | |
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 | |
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 | |
reset_engine()
把当前引擎恢复为出厂默认(tksvg),返回该引擎。
源代码位于: tkdeft\engines\base.py
651 652 653 | |
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 | |
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 | |