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.
- {tkfluent-0.1.6 → tkfluent-0.2.0}/PKG-INFO +167 -39
- {tkfluent-0.1.6 → tkfluent-0.2.0}/README.md +157 -35
- {tkfluent-0.1.6 → tkfluent-0.2.0}/pyproject.toml +21 -3
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/__init__.py +7 -2
- tkfluent-0.2.0/tkflu/__main__.py +710 -0
- tkfluent-0.2.0/tkflu/_after.py +129 -0
- tkfluent-0.2.0/tkflu/badge.py +297 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/button.py +217 -81
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/bwm.py +48 -18
- tkfluent-0.2.0/tkflu/constants.py +30 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/customwindow.py +14 -8
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/customwindow2.py +5 -3
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/defs.py +13 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/__init__.py +1 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/acrylic1.py +1 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/demo1.py +0 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/designer.py +9 -3
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/grad.py +9 -12
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/grad2.py +8 -2
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/grad3.py +8 -2
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/screenshot.py +1 -3
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/scroll.py +2 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/tooltip.py +4 -3
- tkfluent-0.2.0/tkflu/designs/__init__.py +20 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/animation.py +21 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/badge.py +2 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/button.py +5 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/design.py +17 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/entry.py +2 -26
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/fonts/__init__.py +22 -2
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/frame.py +3 -1
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/gradient.py +10 -7
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/label.py +2 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/menubar.py +2 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/primary_color.py +18 -2
- tkfluent-0.2.0/tkflu/designs/renderer.py +191 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/scrollbar.py +4 -2
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/slider.py +20 -92
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/text.py +2 -26
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/tooltip.py +4 -2
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/window.py +6 -4
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/entry.py +165 -72
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/frame.py +162 -58
- tkfluent-0.2.0/tkflu/icons.py +119 -0
- tkfluent-0.2.0/tkflu/image.py +92 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/label.py +41 -19
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/listbox.py +128 -47
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/menu.py +25 -9
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/menubar.py +64 -21
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/popupmenu.py +23 -8
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/popupwindow.py +25 -9
- tkfluent-0.2.0/tkflu/render_manager.py +174 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/scrollbar.py +97 -55
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/slider.py +279 -136
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/text.py +160 -72
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/thememanager.py +22 -6
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/togglebutton.py +199 -78
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/tooltip.py +47 -25
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/toplevel.py +19 -6
- tkfluent-0.2.0/tkflu/window.py +68 -0
- tkfluent-0.1.6/tkflu/__main__.py +0 -137
- tkfluent-0.1.6/tkflu/badge.py +0 -192
- tkfluent-0.1.6/tkflu/constants.py +0 -25
- tkfluent-0.1.6/tkflu/demos/demo.py +0 -137
- tkfluent-0.1.6/tkflu/designs/__init__.py +0 -6
- tkfluent-0.1.6/tkflu/designs/renderer.py +0 -19
- tkfluent-0.1.6/tkflu/icons.py +0 -47
- tkfluent-0.1.6/tkflu/image.py +0 -4
- tkfluent-0.1.6/tkflu/window.py +0 -38
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/checkbox.py +0 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/demos/test.py +0 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/fonts/segoe_fluent_icons.ttf +0 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/designs/fonts/segoeui.ttf +0 -0
- {tkfluent-0.1.6 → tkfluent-0.2.0}/tkflu/litenav.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: tkfluent
|
|
3
|
-
Version: 0.
|
|
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
|
|
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.
|
|
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
|

|
|
48
54
|

|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
├──
|
|
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
|
-
|
|
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
|

|
|
10
10
|

|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
├──
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
+
#
|