tkfluent 0.1.6__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {tkfluent-0.1.6 → tkfluent-0.2.0}/PKG-INFO +167 -39
  2. {tkfluent-0.1.6 → tkfluent-0.2.0}/README.md +157 -35
  3. {tkfluent-0.1.6 → tkfluent-0.2.0}/pyproject.toml +21 -3
  4. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/__init__.py +7 -2
  5. tkfluent-0.2.0/tkflu/__main__.py +710 -0
  6. tkfluent-0.2.0/tkflu/_after.py +129 -0
  7. tkfluent-0.2.0/tkflu/badge.py +297 -0
  8. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/button.py +217 -81
  9. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/bwm.py +48 -18
  10. tkfluent-0.2.0/tkflu/constants.py +30 -0
  11. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/customwindow.py +14 -8
  12. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/customwindow2.py +5 -3
  13. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/defs.py +13 -1
  14. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/__init__.py +1 -1
  15. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/acrylic1.py +1 -1
  16. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/demo1.py +0 -1
  17. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/designer.py +9 -3
  18. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/grad.py +9 -12
  19. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/grad2.py +8 -2
  20. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/grad3.py +8 -2
  21. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/screenshot.py +1 -3
  22. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/scroll.py +2 -1
  23. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/tooltip.py +4 -3
  24. tkfluent-0.2.0/tkflu/designs/__init__.py +20 -0
  25. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/animation.py +21 -0
  26. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/badge.py +2 -0
  27. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/button.py +5 -0
  28. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/design.py +17 -1
  29. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/entry.py +2 -26
  30. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/fonts/__init__.py +22 -2
  31. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/frame.py +3 -1
  32. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/gradient.py +10 -7
  33. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/label.py +2 -0
  34. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/menubar.py +2 -0
  35. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/primary_color.py +18 -2
  36. tkfluent-0.2.0/tkflu/designs/renderer.py +191 -0
  37. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/scrollbar.py +4 -2
  38. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/slider.py +20 -92
  39. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/text.py +2 -26
  40. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/tooltip.py +4 -2
  41. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/window.py +6 -4
  42. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/entry.py +165 -72
  43. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/frame.py +162 -58
  44. tkfluent-0.2.0/tkflu/icons.py +119 -0
  45. tkfluent-0.2.0/tkflu/image.py +92 -0
  46. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/label.py +41 -19
  47. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/listbox.py +128 -47
  48. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/menu.py +25 -9
  49. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/menubar.py +64 -21
  50. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/popupmenu.py +23 -8
  51. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/popupwindow.py +25 -9
  52. tkfluent-0.2.0/tkflu/render_manager.py +174 -0
  53. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/scrollbar.py +97 -55
  54. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/slider.py +279 -136
  55. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/text.py +160 -72
  56. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/thememanager.py +22 -6
  57. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/togglebutton.py +199 -78
  58. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/tooltip.py +47 -25
  59. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/toplevel.py +19 -6
  60. tkfluent-0.2.0/tkflu/window.py +68 -0
  61. tkfluent-0.1.6/tkflu/__main__.py +0 -137
  62. tkfluent-0.1.6/tkflu/badge.py +0 -192
  63. tkfluent-0.1.6/tkflu/constants.py +0 -25
  64. tkfluent-0.1.6/tkflu/demos/demo.py +0 -137
  65. tkfluent-0.1.6/tkflu/designs/__init__.py +0 -6
  66. tkfluent-0.1.6/tkflu/designs/renderer.py +0 -19
  67. tkfluent-0.1.6/tkflu/icons.py +0 -47
  68. tkfluent-0.1.6/tkflu/image.py +0 -4
  69. tkfluent-0.1.6/tkflu/window.py +0 -38
  70. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/checkbox.py +0 -0
  71. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/test.py +0 -0
  72. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/fonts/segoe_fluent_icons.ttf +0 -0
  73. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/fonts/segoeui.ttf +0 -0
  74. {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/litenav.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: tkfluent
3
- Version: 0.1.6
3
+ Version: 0.2.0
4
4
  Summary: Fluent(SunValley) Design for Tkinter. Modern GUI
5
5
  License: GPL-3.0
6
6
  Keywords: tkfluent,tksvg,tkinter,fluent,modern,GUI,interface
@@ -24,13 +24,19 @@ Classifier: Programming Language :: Python :: 3.10
24
24
  Classifier: Programming Language :: Python :: 3.11
25
25
  Classifier: Programming Language :: Python :: 3.12
26
26
  Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: 3.14
27
28
  Classifier: Programming Language :: Tcl
28
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
30
+ Provides-Extra: cairo
31
+ Provides-Extra: raster
32
+ Provides-Extra: skia
29
33
  Requires-Dist: easydict (>=1.13,<2.0)
30
34
  Requires-Dist: numpy
31
- Requires-Dist: pillow (>=10.2.0,<11.0.0)
35
+ Requires-Dist: pillow (>=10.2)
36
+ Requires-Dist: pycairo (>=1.29,<2.0) ; extra == "cairo" or extra == "raster"
37
+ Requires-Dist: skia-python (>=138.0,<139.0) ; extra == "skia" or extra == "raster"
32
38
  Requires-Dist: svgwrite (>=1.4.3,<2.0.0)
33
- Requires-Dist: tkdeft (==0.1.2)
39
+ Requires-Dist: tkdeft (==0.2.0)
34
40
  Requires-Dist: tkextrafont (>=0.6.3,<0.7.0)
35
41
  Requires-Dist: tksvg (>=0.7.4,<0.8.0)
36
42
  Project-URL: Documentation, https://tkfluent.netlify.app
@@ -47,54 +53,176 @@ Description-Content-Type: text/markdown
47
53
  ![Light.png](https://img.picui.cn/free/2025/06/22/6857e613bc150.png)
48
54
  ![Dark.png](https://img.picui.cn/free/2025/06/22/6857e613b7fc2.png)
49
55
 
56
+ ## 环境要求
57
+
58
+ | 依赖 | 版本 | 说明 |
59
+ | --- | --- | --- |
60
+ | Python | `>=3.8` | |
61
+ | `tkdeft` | **`>=0.2.0`** | 绘制引擎层 `tkdeft.engines` 从 0.2.0 开始提供 |
62
+ | `tksvg` / `tkextrafont` / `svgwrite` | 见 `pyproject.toml` | 由 pip 自动安装 |
63
+ | `pillow` | `>=10.2` | **不设上界**,10 / 11 / 12 均可用 |
64
+ | `numpy` | 任意 | |
65
+
66
+ > **⚠️ 本地开发时的常见坑**
67
+ >
68
+ > 如果两个仓库都在本机,IDE 会把项目根加进 `sys.path`,于是
69
+ > `import tkflu` 用的是本地新代码,而 `tkdeft` 仍解析到 site-packages 里的
70
+ > **旧版本**,导入时报:
71
+ >
72
+ > ```text
73
+ > ModuleNotFoundError: No module named 'tkdeft.engines'
74
+ > ```
75
+ >
76
+ > 解决办法:把两个仓库都装成可编辑模式(**先装被依赖的**):
77
+ >
78
+ > ```bash
79
+ > pip install -e ../tkdeft
80
+ > pip install -e .
81
+ > ```
82
+ >
83
+ > 确认环境是否正确:
84
+ >
85
+ > ```bash
86
+ > python -c "import tkdeft; print(tkdeft.__version__, tkdeft.__file__)"
87
+ > # 期望输出 0.2.0 以及你本地 tkdeft 仓库的路径
88
+ > ```
89
+ >
90
+ > 可选的更快绘制引擎(不装也能用,会退回 tksvg / Pillow):
91
+ >
92
+ > ```bash
93
+ > cd ../tkdeft
94
+ > pip install -e ".[skia]" # skia-python
95
+ > pip install -e ".[raster]" # skia-python + pycairo
96
+ > ```
97
+
50
98
  ## 文档
51
99
  请查阅[tkfluent文档网站](https://tkfluent.netlify.app/)。
52
100
  使用`mkdocs`和`mkdocs-material`构建,由`netlify`部署
53
101
 
102
+ 主要章节:
103
+
104
+ | 章节 | 内容 |
105
+ | --- | --- |
106
+ | [Get Started](docs/docs/getstarted/download.md) | 安装、上手、第一个应用 |
107
+ | [Guide 指南](docs/docs/guide/components.md) | [组件总览](docs/docs/guide/components.md)、[运行演示](docs/docs/guide/run-demo.md)、[主题与配色](docs/docs/guide/theme.md) |
108
+ | [Tutorial 教程](docs/docs/tutorial/renderer.md) | [渲染引擎与性能](docs/docs/tutorial/renderer.md)、主题切换、提示气泡 |
109
+ | [API 文档](docs/docs/api/index.md) | 由源码 docstring 自动生成(`mkdocstrings`) |
110
+
111
+ ### 本地构建文档
112
+
113
+ ```bash
114
+ pip install -r docs/requirements.txt
115
+ mkdocs serve -f docs/mkdocs.yml # 本地预览
116
+ mkdocs build --strict -f docs/mkdocs.yml
117
+ ```
118
+
119
+ 新增公开模块后,用 `python docs/gen_api_pages.py --write` 重新生成 API 页面,
120
+ 并把打印出来的 nav 片段同步到 `docs/mkdocs.yml`。
121
+
122
+ ## 快速看效果
123
+
124
+ 不需要写代码,直接运行内置的组件画廊:
125
+
126
+ ```bash
127
+ python -m tkflu # 或者安装后:tkfluent-demo
128
+ python -m tkflu -r auto # 用最快的可用渲染引擎
129
+ python -m tkflu --list-engines # 看看哪些引擎可用
130
+ python -m tkflu --check # 无界面自检(CI 可用,成功返回 0)
131
+ ```
132
+
133
+ 画廊把全部组件摆在同一个窗口里(左栏内容型、右栏交互型、顶部菜单栏、
134
+ 底部状态栏显示当前引擎与缓存命中率),点任何组件都会打印事件日志。
135
+ 完整参数见 [运行演示](docs/docs/guide/run-demo.md)。
136
+
54
137
  ## 贡献者
55
138
  1. [真_人工智障](https://github.com/TotoWang-hhh)
56
139
 
57
140
  ## 依赖图
58
- ```bash
59
- PS .\tkfluent> poetry show --tree
60
- easydict 1.13 Access dict values as attributes (works recursively).
61
- numpy 1.24.4 Fundamental package for array computing in Python
62
- pillow 10.4.0 Python Imaging Library (Fork)
63
- svgwrite 1.4.3 A Python library to create SVG drawings.
64
- tkdeft 0.0.9 使用tkinter+tksvg开发的现代化界面库
65
- ├── easydict >=1.13,<2.0
66
- ├── pillow >=10.2.0,<11.0.0
67
- ├── svgwrite >=1.4.3,<2.0.0
141
+
142
+ 直接依赖(`poetry show --tree`,会随版本变化,以 `pyproject.toml` 为准):
143
+
144
+ ```text
145
+ easydict ^1.13 属性式字典,组件用它存状态
146
+ numpy * 渐变插值、栅格引擎的像素运算
147
+ pillow >=10.2 位图处理与 PhotoImage 转换
148
+ svgwrite ^1.4.3 生成 SVG(SVG 引擎路径)
149
+ tkdeft 0.2.0 绘制引擎层 / 画布 / 交互控件基类
150
+ ├── easydict >=1.13
151
+ ├── pillow >=10.2
152
+ ├── numpy *
153
+ ├── svgwrite >=1.4.3,<2.0.0
68
154
  ├── tkextrafont >=0.6.3,<0.7.0
69
155
  │ └── scikit-build *
70
- │ ├── distro *
71
- │ ├── packaging *
72
- │ ├── setuptools >=42.0.0
73
- │ ├── tomli *
74
- │ └── wheel >=0.32.0
75
- └── tksvg >=0.7.4,<0.8.0
156
+ └── tksvg >=0.7.4,<0.8.0
76
157
  └── scikit-build *
77
- ├── distro *
78
- ├── packaging *
79
- ├── setuptools >=42.0.0
80
- ├── tomli *
81
- └── wheel >=0.32.0
82
- tkextrafont 0.6.3 Fonts loader for Tkinter
83
- └── scikit-build *
84
- ├── distro *
85
- ├── packaging *
86
- ├── setuptools >=42.0.0
87
- ├── tomli *
88
- └── wheel >=0.32.0
89
- tksvg 0.7.4 SVG support for PhotoImage in Tk 8.6
90
- └── scikit-build *
91
- ├── distro *
92
- ├── packaging *
93
- ├── setuptools >=42.0.0
94
- ├── tomli *
95
- └── wheel >=0.32.0
96
158
  ```
97
159
 
160
+ 完整依赖树(含间接依赖)可以自己跑一遍:
161
+
162
+ ```bash
163
+ poetry show --tree
164
+ ```
165
+
166
+ ## 渲染引擎与性能
167
+
168
+ `tkfluent` 的绘制后端现在是**可切换**的,底层由
169
+ [`tkdeft.engines`](https://pypi.org/project/tkdeft) 提供。
170
+
171
+ ```python
172
+ from tkflu.designs.renderer import set_renderer, list_renderers
173
+
174
+ print(list_renderers())
175
+ # [(0, 'tksvg', True), (1, 'wand', True), (2, 'skia', True), (3, 'pillow', True), (4, 'cairo', True)]
176
+
177
+ set_renderer("skia") # 也接受编号:set_renderer(2)
178
+ ```
179
+
180
+ | 编号 | 引擎 | 类型 | 额外依赖 |
181
+ | --- | --- | --- | --- |
182
+ | `0` | `tksvg` | SVG,**默认,行为与旧版完全一致** | 无 |
183
+ | `1` | `wand` | SVG → PNG | `Wand` |
184
+ | `2` | `skia` | 进程内栅格,速度与画质最好 | `pip install tkfluent[skia]` |
185
+ | `3` | `pillow` | 进程内栅格,**永远可用** | 无 |
186
+ | `4` | `cairo` | 进程内栅格 | `pip install tkfluent[cairo]` |
187
+
188
+ 旧写法依然有效:
189
+
190
+ ```python
191
+ from tkflu.designs.renderer import set_renderer
192
+ set_renderer(0) # 之前的 0/1 语义不变
193
+ ```
194
+
195
+ > **为什么不直接默认换成 skia?**
196
+ > 栅格引擎在抗锯齿细节上与 tksvg 有亚像素级差异,为了让老项目升级后
197
+ > 界面**一个像素都不变**,默认仍是 `tksvg`。想要性能就显式切到 `2` 或 `3`。
198
+
199
+ ### 实测提升(本机)
200
+
201
+ | 场景 | `tksvg`(默认) | `skia`(编号 2) | 提升 |
202
+ | --- | --- | --- | --- |
203
+ | 按钮重绘 | 5.95 ms | 0.15 ms | **39×** |
204
+ | 按钮 hover 往返 | 13.65 ms | 0.26 ms | **52×** |
205
+ | 20 个按钮批量重绘 | 139.9 ms | 2.93 ms | **48×** |
206
+ | 圆角矩形(参数相同,命中缓存) | 10.80 ms | 0.02 ms | **480×** |
207
+
208
+ 即使完全不动渲染引擎,这一版对 `tkdeft` 基础设施的修复(临时文件/fd 泄漏、
209
+ 图片被 GC 导致画面空白、无效的重复重绘)本身也能带来约 **2–3×** 的改善。
210
+
211
+ 复现:`python benchmarks/run_all.py`(在 `tkdeft` 仓库里)
212
+
213
+ ### 这一版修掉的组件层缺陷
214
+
215
+ | 问题 | 影响 |
216
+ | --- | --- |
217
+ | `FluSlider._draw` 用 `if renderer == 0 / elif == 1` 且**没有 else** | 新增渲染器编号时轨道与把手不会被创建,构造即 `AttributeError` |
218
+ | `FluFrame._draw` 每次重绘都挂两个 `after(100)` 且从不取消 | 拖动窗口时回调堆积卡顿;关窗后控制台刷 `invalid command name` |
219
+ | `FluFrame._draw` 调用了 `self.update()` | 会处理全部事件(含 `<Configure>`),在 `_draw` 内部重入 |
220
+ | `FluBadge._draw` 每次重绘都挂 `after(10, lambda: self.update())` | 同类回调泄漏 |
221
+ | `icons.py` 每次调用都 `mkstemp()` 且不关闭 fd | 每开一个窗口泄漏一个句柄 + 一个残留文件 |
222
+ | `window.py` / `toplevel.py` 的 `PhotoImage` 未指定 `master` | 多 Tk 解释器场景下 `iconphoto` 报 `not a photo image` |
223
+ | 圆角矩形几何用 `translate(0.5,0.5)` | **按钮的下边框和右边框被完全裁掉** |
224
+ | `RenderManager` 调用不存在的 `winfo_zorder` | 开启 `optimized_rendering` 后每次渲染都抛异常 |
225
+
98
226
  ## 协议
99
227
  本项目采用`GPL-3.0`协议
100
228
 
@@ -9,54 +9,176 @@
9
9
  ![Light.png](https://img.picui.cn/free/2025/06/22/6857e613bc150.png)
10
10
  ![Dark.png](https://img.picui.cn/free/2025/06/22/6857e613b7fc2.png)
11
11
 
12
+ ## 环境要求
13
+
14
+ | 依赖 | 版本 | 说明 |
15
+ | --- | --- | --- |
16
+ | Python | `>=3.8` | |
17
+ | `tkdeft` | **`>=0.2.0`** | 绘制引擎层 `tkdeft.engines` 从 0.2.0 开始提供 |
18
+ | `tksvg` / `tkextrafont` / `svgwrite` | 见 `pyproject.toml` | 由 pip 自动安装 |
19
+ | `pillow` | `>=10.2` | **不设上界**,10 / 11 / 12 均可用 |
20
+ | `numpy` | 任意 | |
21
+
22
+ > **⚠️ 本地开发时的常见坑**
23
+ >
24
+ > 如果两个仓库都在本机,IDE 会把项目根加进 `sys.path`,于是
25
+ > `import tkflu` 用的是本地新代码,而 `tkdeft` 仍解析到 site-packages 里的
26
+ > **旧版本**,导入时报:
27
+ >
28
+ > ```text
29
+ > ModuleNotFoundError: No module named 'tkdeft.engines'
30
+ > ```
31
+ >
32
+ > 解决办法:把两个仓库都装成可编辑模式(**先装被依赖的**):
33
+ >
34
+ > ```bash
35
+ > pip install -e ../tkdeft
36
+ > pip install -e .
37
+ > ```
38
+ >
39
+ > 确认环境是否正确:
40
+ >
41
+ > ```bash
42
+ > python -c "import tkdeft; print(tkdeft.__version__, tkdeft.__file__)"
43
+ > # 期望输出 0.2.0 以及你本地 tkdeft 仓库的路径
44
+ > ```
45
+ >
46
+ > 可选的更快绘制引擎(不装也能用,会退回 tksvg / Pillow):
47
+ >
48
+ > ```bash
49
+ > cd ../tkdeft
50
+ > pip install -e ".[skia]" # skia-python
51
+ > pip install -e ".[raster]" # skia-python + pycairo
52
+ > ```
53
+
12
54
  ## 文档
13
55
  请查阅[tkfluent文档网站](https://tkfluent.netlify.app/)。
14
56
  使用`mkdocs`和`mkdocs-material`构建,由`netlify`部署
15
57
 
58
+ 主要章节:
59
+
60
+ | 章节 | 内容 |
61
+ | --- | --- |
62
+ | [Get Started](docs/docs/getstarted/download.md) | 安装、上手、第一个应用 |
63
+ | [Guide 指南](docs/docs/guide/components.md) | [组件总览](docs/docs/guide/components.md)、[运行演示](docs/docs/guide/run-demo.md)、[主题与配色](docs/docs/guide/theme.md) |
64
+ | [Tutorial 教程](docs/docs/tutorial/renderer.md) | [渲染引擎与性能](docs/docs/tutorial/renderer.md)、主题切换、提示气泡 |
65
+ | [API 文档](docs/docs/api/index.md) | 由源码 docstring 自动生成(`mkdocstrings`) |
66
+
67
+ ### 本地构建文档
68
+
69
+ ```bash
70
+ pip install -r docs/requirements.txt
71
+ mkdocs serve -f docs/mkdocs.yml # 本地预览
72
+ mkdocs build --strict -f docs/mkdocs.yml
73
+ ```
74
+
75
+ 新增公开模块后,用 `python docs/gen_api_pages.py --write` 重新生成 API 页面,
76
+ 并把打印出来的 nav 片段同步到 `docs/mkdocs.yml`。
77
+
78
+ ## 快速看效果
79
+
80
+ 不需要写代码,直接运行内置的组件画廊:
81
+
82
+ ```bash
83
+ python -m tkflu # 或者安装后:tkfluent-demo
84
+ python -m tkflu -r auto # 用最快的可用渲染引擎
85
+ python -m tkflu --list-engines # 看看哪些引擎可用
86
+ python -m tkflu --check # 无界面自检(CI 可用,成功返回 0)
87
+ ```
88
+
89
+ 画廊把全部组件摆在同一个窗口里(左栏内容型、右栏交互型、顶部菜单栏、
90
+ 底部状态栏显示当前引擎与缓存命中率),点任何组件都会打印事件日志。
91
+ 完整参数见 [运行演示](docs/docs/guide/run-demo.md)。
92
+
16
93
  ## 贡献者
17
94
  1. [真_人工智障](https://github.com/TotoWang-hhh)
18
95
 
19
96
  ## 依赖图
20
- ```bash
21
- PS .\tkfluent> poetry show --tree
22
- easydict 1.13 Access dict values as attributes (works recursively).
23
- numpy 1.24.4 Fundamental package for array computing in Python
24
- pillow 10.4.0 Python Imaging Library (Fork)
25
- svgwrite 1.4.3 A Python library to create SVG drawings.
26
- tkdeft 0.0.9 使用tkinter+tksvg开发的现代化界面库
27
- ├── easydict >=1.13,<2.0
28
- ├── pillow >=10.2.0,<11.0.0
29
- ├── svgwrite >=1.4.3,<2.0.0
97
+
98
+ 直接依赖(`poetry show --tree`,会随版本变化,以 `pyproject.toml` 为准):
99
+
100
+ ```text
101
+ easydict ^1.13 属性式字典,组件用它存状态
102
+ numpy * 渐变插值、栅格引擎的像素运算
103
+ pillow >=10.2 位图处理与 PhotoImage 转换
104
+ svgwrite ^1.4.3 生成 SVG(SVG 引擎路径)
105
+ tkdeft 0.2.0 绘制引擎层 / 画布 / 交互控件基类
106
+ ├── easydict >=1.13
107
+ ├── pillow >=10.2
108
+ ├── numpy *
109
+ ├── svgwrite >=1.4.3,<2.0.0
30
110
  ├── tkextrafont >=0.6.3,<0.7.0
31
111
  │ └── scikit-build *
32
- │ ├── distro *
33
- │ ├── packaging *
34
- │ ├── setuptools >=42.0.0
35
- │ ├── tomli *
36
- │ └── wheel >=0.32.0
37
- └── tksvg >=0.7.4,<0.8.0
112
+ └── tksvg >=0.7.4,<0.8.0
38
113
  └── scikit-build *
39
- ├── distro *
40
- ├── packaging *
41
- ├── setuptools >=42.0.0
42
- ├── tomli *
43
- └── wheel >=0.32.0
44
- tkextrafont 0.6.3 Fonts loader for Tkinter
45
- └── scikit-build *
46
- ├── distro *
47
- ├── packaging *
48
- ├── setuptools >=42.0.0
49
- ├── tomli *
50
- └── wheel >=0.32.0
51
- tksvg 0.7.4 SVG support for PhotoImage in Tk 8.6
52
- └── scikit-build *
53
- ├── distro *
54
- ├── packaging *
55
- ├── setuptools >=42.0.0
56
- ├── tomli *
57
- └── wheel >=0.32.0
58
114
  ```
59
115
 
116
+ 完整依赖树(含间接依赖)可以自己跑一遍:
117
+
118
+ ```bash
119
+ poetry show --tree
120
+ ```
121
+
122
+ ## 渲染引擎与性能
123
+
124
+ `tkfluent` 的绘制后端现在是**可切换**的,底层由
125
+ [`tkdeft.engines`](https://pypi.org/project/tkdeft) 提供。
126
+
127
+ ```python
128
+ from tkflu.designs.renderer import set_renderer, list_renderers
129
+
130
+ print(list_renderers())
131
+ # [(0, 'tksvg', True), (1, 'wand', True), (2, 'skia', True), (3, 'pillow', True), (4, 'cairo', True)]
132
+
133
+ set_renderer("skia") # 也接受编号:set_renderer(2)
134
+ ```
135
+
136
+ | 编号 | 引擎 | 类型 | 额外依赖 |
137
+ | --- | --- | --- | --- |
138
+ | `0` | `tksvg` | SVG,**默认,行为与旧版完全一致** | 无 |
139
+ | `1` | `wand` | SVG → PNG | `Wand` |
140
+ | `2` | `skia` | 进程内栅格,速度与画质最好 | `pip install tkfluent[skia]` |
141
+ | `3` | `pillow` | 进程内栅格,**永远可用** | 无 |
142
+ | `4` | `cairo` | 进程内栅格 | `pip install tkfluent[cairo]` |
143
+
144
+ 旧写法依然有效:
145
+
146
+ ```python
147
+ from tkflu.designs.renderer import set_renderer
148
+ set_renderer(0) # 之前的 0/1 语义不变
149
+ ```
150
+
151
+ > **为什么不直接默认换成 skia?**
152
+ > 栅格引擎在抗锯齿细节上与 tksvg 有亚像素级差异,为了让老项目升级后
153
+ > 界面**一个像素都不变**,默认仍是 `tksvg`。想要性能就显式切到 `2` 或 `3`。
154
+
155
+ ### 实测提升(本机)
156
+
157
+ | 场景 | `tksvg`(默认) | `skia`(编号 2) | 提升 |
158
+ | --- | --- | --- | --- |
159
+ | 按钮重绘 | 5.95 ms | 0.15 ms | **39×** |
160
+ | 按钮 hover 往返 | 13.65 ms | 0.26 ms | **52×** |
161
+ | 20 个按钮批量重绘 | 139.9 ms | 2.93 ms | **48×** |
162
+ | 圆角矩形(参数相同,命中缓存) | 10.80 ms | 0.02 ms | **480×** |
163
+
164
+ 即使完全不动渲染引擎,这一版对 `tkdeft` 基础设施的修复(临时文件/fd 泄漏、
165
+ 图片被 GC 导致画面空白、无效的重复重绘)本身也能带来约 **2–3×** 的改善。
166
+
167
+ 复现:`python benchmarks/run_all.py`(在 `tkdeft` 仓库里)
168
+
169
+ ### 这一版修掉的组件层缺陷
170
+
171
+ | 问题 | 影响 |
172
+ | --- | --- |
173
+ | `FluSlider._draw` 用 `if renderer == 0 / elif == 1` 且**没有 else** | 新增渲染器编号时轨道与把手不会被创建,构造即 `AttributeError` |
174
+ | `FluFrame._draw` 每次重绘都挂两个 `after(100)` 且从不取消 | 拖动窗口时回调堆积卡顿;关窗后控制台刷 `invalid command name` |
175
+ | `FluFrame._draw` 调用了 `self.update()` | 会处理全部事件(含 `<Configure>`),在 `_draw` 内部重入 |
176
+ | `FluBadge._draw` 每次重绘都挂 `after(10, lambda: self.update())` | 同类回调泄漏 |
177
+ | `icons.py` 每次调用都 `mkstemp()` 且不关闭 fd | 每开一个窗口泄漏一个句柄 + 一个残留文件 |
178
+ | `window.py` / `toplevel.py` 的 `PhotoImage` 未指定 `master` | 多 Tk 解释器场景下 `iconphoto` 报 `not a photo image` |
179
+ | 圆角矩形几何用 `translate(0.5,0.5)` | **按钮的下边框和右边框被完全裁掉** |
180
+ | `RenderManager` 调用不存在的 `winfo_zorder` | 开启 `optimized_rendering` 后每次渲染都抛异常 |
181
+
60
182
  ## 协议
61
183
  本项目采用`GPL-3.0`协议
62
184
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tkfluent"
3
- version = "0.1.6"
3
+ version = "0.2.0"
4
4
  description = "Fluent(SunValley) Design for Tkinter. Modern GUI"
5
5
  authors = ["XiangQinxi <xiangqinxi@outlook.com>"]
6
6
  readme = "README.md"
@@ -36,11 +36,29 @@ python = "^3.8"
36
36
  tksvg = "^0.7.4"
37
37
  tkextrafont = "^0.6.3"
38
38
  svgwrite = "^1.4.3"
39
- pillow = "^10.2.0"
40
- tkdeft = "0.1.2"
39
+ # 与 tkdeft 保持一致,不设上界(Pillow 10 / 11 / 12 实测均可用)
40
+ pillow = ">=10.2"
41
+ tkdeft = "0.2.0"
41
42
  easydict = "^1.13"
42
43
  numpy = "*"
43
44
 
45
+ # 可选的进程内栅格绘制引擎(渲染器 2 / 4)。不装也能用:
46
+ # 渲染器 0(tksvg,默认)与 3(Pillow)不需要任何额外依赖。
47
+ skia-python = { version = "^138.0", optional = true }
48
+ pycairo = { version = "^1.29", optional = true }
49
+
50
+ [tool.poetry.scripts]
51
+ # 安装后可用的命令:
52
+ # tkfluent-demo 启动组件画廊
53
+ # tkfluent-demo -r skia 指定渲染引擎
54
+ # tkfluent-demo --check 无界面自检(CI 可用)
55
+ tkfluent-demo = "tkflu.__main__:main"
56
+
57
+ [tool.poetry.extras]
58
+ skia = ["skia-python"]
59
+ cairo = ["pycairo"]
60
+ raster = ["skia-python", "pycairo"]
61
+
44
62
  [build-system]
45
63
  requires = ["poetry-core"]
46
64
  build-backend = "poetry.core.masonry.api"
@@ -14,10 +14,13 @@ from .button import FluButton
14
14
  from .bwm import BWm
15
15
  from .constants import *
16
16
  from .defs import *
17
+ from .designs import *
17
18
  from .entry import FluEntry
18
19
  from .frame import FluFrame
19
20
  from .icons import *
21
+ from .image import FluImage
20
22
  from .label import FluLabel
23
+ from .listbox import FluListBox
21
24
  from .menu import FluMenu
22
25
  from .menubar import FluMenuBar
23
26
  from .popupmenu import FluPopupMenu, FluPopupMenuWindow
@@ -31,7 +34,9 @@ from .tooltip import FluToolTip, FluToolTip2, FluToolTipBase
31
34
  from .toplevel import FluToplevel
32
35
  from .window import FluWindow
33
36
 
34
- from .designs import *
37
+ # 说明:FluListBox 与 FluImage 此前没有出现在包根,
38
+ # 导致 tkflu.FluListBox 不可用(只有 tkflu.listbox.FluListBox)。
39
+ # 这里补上,让所有公开组件都能从包根导入。
35
40
 
36
41
  FluChip = FluBadge
37
42
  FluPushButton = FluButton
@@ -41,4 +46,4 @@ FluPanel = FluFrame
41
46
  FluMainWindow = FluWindow
42
47
  FluSubWindow = FluToplevel
43
48
 
44
- # 
49
+ # 