tkfluent 0.0.9__tar.gz → 0.1.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.0.9 → tkfluent-0.1.0}/PKG-INFO +2 -1
- {tkfluent-0.0.9 → tkfluent-0.1.0}/pyproject.toml +2 -1
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/bwm.py +14 -1
- tkfluent-0.1.0/tkflu/demos/demo1.py +8 -0
- tkfluent-0.1.0/tkflu/demos/grad.py +70 -0
- tkfluent-0.1.0/tkflu/demos/grad2.py +140 -0
- tkfluent-0.1.0/tkflu/demos/grad3.py +22 -0
- tkfluent-0.1.0/tkflu/demos/test.py +8 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/demos/tooltip.py +1 -1
- tkfluent-0.1.0/tkflu/designs/gradient.py +54 -0
- tkfluent-0.1.0/tkflu/designs/menubar.py +13 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/frame.py +2 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/menu.py +1 -1
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/menubar.py +34 -12
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/togglebutton.py +125 -32
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/tooltip.py +2 -2
- {tkfluent-0.0.9 → tkfluent-0.1.0}/README.md +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/__init__.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/__main__.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/badge.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/button.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/checkbox.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/constants.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/customwindow.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/customwindow2.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/defs.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/demos/__init__.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/demos/acrylic1.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/__init__.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/badge.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/button.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/design.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/entry.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/fonts/__init__.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/fonts/segoeui.ttf +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/frame.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/primary_color.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/slider.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/text.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/tooltip.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/window.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/entry.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/icons.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/image.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/label.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/listbox.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/litenav.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/popupmenu.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/popupwindow.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/scrollbar.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/slider.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/text.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/thememanager.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/toplevel.py +0 -0
- {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/window.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: tkfluent
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: Fluent Design for Tkinter
|
5
5
|
License: MIT
|
6
6
|
Keywords: tkfluent,tksvg,tkinter,fluent,modern,UI,interface
|
@@ -27,6 +27,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
27
27
|
Classifier: Programming Language :: Tcl
|
28
28
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
29
29
|
Requires-Dist: easydict (>=1.13,<2.0)
|
30
|
+
Requires-Dist: numpy (>=2.3.1,<3.0.0)
|
30
31
|
Requires-Dist: pillow (>=10.2.0,<11.0.0)
|
31
32
|
Requires-Dist: svgwrite (>=1.4.3,<2.0.0)
|
32
33
|
Requires-Dist: tkdeft (>=0.0.9,<0.0.10)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "tkfluent"
|
3
|
-
version = "0.0
|
3
|
+
version = "0.1.0"
|
4
4
|
description = "Fluent Design for Tkinter"
|
5
5
|
authors = ["XiangQinxi <xiangqinxi@outlook.com>"]
|
6
6
|
readme = "README.md"
|
@@ -38,6 +38,7 @@ svgwrite = "^1.4.3"
|
|
38
38
|
pillow = "^10.2.0"
|
39
39
|
tkdeft = "^0.0.9"
|
40
40
|
easydict = "^1.13"
|
41
|
+
numpy = "^2.3.1"
|
41
42
|
|
42
43
|
[build-system]
|
43
44
|
requires = ["poetry-core"]
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
from .designs.gradient import FluGradient
|
2
|
+
|
3
|
+
|
4
|
+
class BWm(FluGradient):
|
2
5
|
def _draw(self, event=None):
|
3
6
|
|
4
7
|
"""
|
@@ -128,6 +131,16 @@ class BWm(object):
|
|
128
131
|
n = window(mode)
|
129
132
|
"""if self.attributes.back_color is not None:
|
130
133
|
n["back_color"] = self.attributes.back_color"""
|
134
|
+
|
135
|
+
if self.dcget("back_color"):
|
136
|
+
back_colors = self.generate_hex2hex(self.dcget("back_color"), n["back_color"], steps=10)
|
137
|
+
for i in range(10):
|
138
|
+
def update(ii=i): # 使用默认参数立即捕获i的值
|
139
|
+
self.dconfigure(back_color=back_colors[ii])
|
140
|
+
self._draw()
|
141
|
+
|
142
|
+
self.after(i * 10, update) # 直接传递函数,不需要lambda
|
143
|
+
|
131
144
|
self.dconfigure(
|
132
145
|
back_color=n["back_color"],
|
133
146
|
text_color=n["text_color"],
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import matplotlib.pyplot as plt
|
2
|
+
import numpy as np
|
3
|
+
|
4
|
+
|
5
|
+
def color_gradient(color1, color2, steps=10, output_format='both'):
|
6
|
+
"""
|
7
|
+
生成颜色渐变序列
|
8
|
+
:param color1: 起始颜色 (RGB元组或HEX字符串)
|
9
|
+
:param color2: 结束颜色 (RGB元组或HEX字符串)
|
10
|
+
:param steps: 渐变步数
|
11
|
+
:param output_format: 输出格式 ('rgb', 'hex' 或 'both')
|
12
|
+
:return: 渐变颜色列表
|
13
|
+
"""
|
14
|
+
|
15
|
+
# 输入格式处理
|
16
|
+
def parse_color(color):
|
17
|
+
if isinstance(color, str): # HEX格式
|
18
|
+
color = color.lstrip('#')
|
19
|
+
return tuple(int(color[i:i + 2], 16) for i in (0, 2, 4))
|
20
|
+
return color # 已经是RGB格式
|
21
|
+
|
22
|
+
rgb1 = np.array(parse_color(color1))
|
23
|
+
rgb2 = np.array(parse_color(color2))
|
24
|
+
|
25
|
+
# 生成渐变
|
26
|
+
gradient = []
|
27
|
+
for t in np.linspace(0, 1, steps):
|
28
|
+
rgb = rgb1 + (rgb2 - rgb1) * t
|
29
|
+
rgb = np.round(rgb).astype(int)
|
30
|
+
rgb_clipped = np.clip(rgb, 0, 255) # 确保在0-255范围内
|
31
|
+
gradient.append(rgb_clipped)
|
32
|
+
|
33
|
+
# 格式转换
|
34
|
+
result = []
|
35
|
+
for color in gradient:
|
36
|
+
r, g, b = color
|
37
|
+
if output_format == 'rgb':
|
38
|
+
result.append(tuple(color))
|
39
|
+
elif output_format == 'hex':
|
40
|
+
result.append(f"#{r:02x}{g:02x}{b:02x}")
|
41
|
+
else: # both
|
42
|
+
result.append({
|
43
|
+
'rgb': tuple(color),
|
44
|
+
'hex': f"#{r:02x}{g:02x}{b:02x}"
|
45
|
+
})
|
46
|
+
|
47
|
+
return result
|
48
|
+
|
49
|
+
|
50
|
+
# 示例使用
|
51
|
+
if __name__ == "__main__":
|
52
|
+
# 输入颜色 (支持RGB或HEX)
|
53
|
+
start_color = "#FF0000" # 红色
|
54
|
+
end_color = (0, 0, 255) # 蓝色
|
55
|
+
|
56
|
+
# 生成渐变 (20个步骤)
|
57
|
+
gradient = color_gradient(start_color, end_color, steps=20, output_format='both')
|
58
|
+
|
59
|
+
# 打印输出
|
60
|
+
print("颜色渐变序列:")
|
61
|
+
for i, color in enumerate(gradient):
|
62
|
+
print(f"{i + 1:2d}: RGB{color['rgb']} -> {color['hex']}")
|
63
|
+
|
64
|
+
# 可视化展示
|
65
|
+
plt.figure(figsize=(10, 2))
|
66
|
+
for i, color in enumerate(gradient):
|
67
|
+
plt.fill_between([i, i + 1], 0, 1, color=np.array(color['rgb']) / 255)
|
68
|
+
plt.title("Color Gradient Visualization")
|
69
|
+
plt.axis('off')
|
70
|
+
plt.show()
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import tkinter as tk
|
2
|
+
from tkinter import ttk
|
3
|
+
import numpy as np
|
4
|
+
|
5
|
+
|
6
|
+
class GradientLabelApp:
|
7
|
+
def __init__(self, root):
|
8
|
+
self.root = root
|
9
|
+
self.root.title("Tkinter渐变标签演示")
|
10
|
+
self.root.geometry("400x200")
|
11
|
+
|
12
|
+
# 渐变控制变量
|
13
|
+
self.is_animating = False
|
14
|
+
self.current_step = 0
|
15
|
+
self.gradient_steps = 20 # 渐变步数
|
16
|
+
|
17
|
+
# 创建UI组件
|
18
|
+
self.create_widgets()
|
19
|
+
|
20
|
+
# 预生成渐变序列 (从蓝色到红色)
|
21
|
+
self.gradient = self.generate_gradient_hex(
|
22
|
+
"#ffffff",
|
23
|
+
"#005fb8",
|
24
|
+
self.gradient_steps
|
25
|
+
)
|
26
|
+
|
27
|
+
def create_widgets(self):
|
28
|
+
"""创建界面组件"""
|
29
|
+
# 渐变显示标签
|
30
|
+
self.label = tk.Label(
|
31
|
+
self.root,
|
32
|
+
text="渐变背景标签",
|
33
|
+
font=('Arial', 20),
|
34
|
+
relief='raised',
|
35
|
+
borderwidth=2
|
36
|
+
)
|
37
|
+
self.label.pack(pady=20, ipadx=50, ipady=30, fill='x', padx=20)
|
38
|
+
|
39
|
+
# 控制按钮框架
|
40
|
+
button_frame = ttk.Frame(self.root)
|
41
|
+
button_frame.pack(pady=10)
|
42
|
+
|
43
|
+
# 开始按钮
|
44
|
+
self.start_button = ttk.Button(
|
45
|
+
button_frame,
|
46
|
+
text="开始渐变",
|
47
|
+
command=self.toggle_animation
|
48
|
+
)
|
49
|
+
self.start_button.pack(side='left', padx=5)
|
50
|
+
|
51
|
+
# 重置按钮
|
52
|
+
ttk.Button(
|
53
|
+
button_frame,
|
54
|
+
text="重置",
|
55
|
+
command=self.reset_animation
|
56
|
+
).pack(side='left', padx=5)
|
57
|
+
|
58
|
+
def generate_gradient(self, start_color, end_color, steps):
|
59
|
+
"""生成颜色渐变序列"""
|
60
|
+
gradient = []
|
61
|
+
for t in np.linspace(0, 1, steps):
|
62
|
+
r = int(start_color[0] + (end_color[0] - start_color[0]) * t)
|
63
|
+
g = int(start_color[1] + (end_color[1] - start_color[1]) * t)
|
64
|
+
b = int(start_color[2] + (end_color[2] - start_color[2]) * t)
|
65
|
+
gradient.append(f"#{r:02x}{g:02x}{b:02x}")
|
66
|
+
return gradient
|
67
|
+
|
68
|
+
def generate_gradient_hex(self, start_hex, end_hex, steps):
|
69
|
+
"""
|
70
|
+
专为HEX颜色设计的渐变生成器
|
71
|
+
:param start_hex: 起始颜色 HEX格式 (如 "#FF0000")
|
72
|
+
:param end_hex: 结束颜色 HEX格式 (如 "#0000FF")
|
73
|
+
:param steps: 渐变步数
|
74
|
+
:return: HEX格式的颜色列表
|
75
|
+
"""
|
76
|
+
|
77
|
+
# 去除#号并转换为RGB元组
|
78
|
+
def hex_to_rgb(h):
|
79
|
+
h = h.lstrip('#')
|
80
|
+
return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
|
81
|
+
|
82
|
+
# RGB转HEX
|
83
|
+
def rgb_to_hex(rgb):
|
84
|
+
return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"
|
85
|
+
|
86
|
+
rgb_start = hex_to_rgb(start_hex)
|
87
|
+
rgb_end = hex_to_rgb(end_hex)
|
88
|
+
|
89
|
+
gradient = []
|
90
|
+
for t in np.linspace(0, 1, steps):
|
91
|
+
# 计算每个通道的中间值
|
92
|
+
r = int(rgb_start[0] + (rgb_end[0] - rgb_start[0]) * t)
|
93
|
+
g = int(rgb_start[1] + (rgb_end[1] - rgb_start[1]) * t)
|
94
|
+
b = int(rgb_start[2] + (rgb_end[2] - rgb_start[2]) * t)
|
95
|
+
|
96
|
+
# 确保值在0-255范围内并转换为HEX
|
97
|
+
gradient.append(rgb_to_hex((
|
98
|
+
max(0, min(255, r)),
|
99
|
+
max(0, min(255, g)),
|
100
|
+
max(0, min(255, b))
|
101
|
+
)))
|
102
|
+
|
103
|
+
return gradient
|
104
|
+
|
105
|
+
def toggle_animation(self):
|
106
|
+
"""切换动画状态"""
|
107
|
+
self.is_animating = not self.is_animating
|
108
|
+
self.start_button.config(
|
109
|
+
text="停止渐变" if self.is_animating else "开始渐变"
|
110
|
+
)
|
111
|
+
if self.is_animating:
|
112
|
+
self.animate_gradient()
|
113
|
+
|
114
|
+
def animate_gradient(self):
|
115
|
+
"""执行渐变动画"""
|
116
|
+
if not self.is_animating:
|
117
|
+
return
|
118
|
+
|
119
|
+
# 更新标签背景色
|
120
|
+
color = self.gradient[self.current_step]
|
121
|
+
self.label.config(background=color)
|
122
|
+
|
123
|
+
# 更新步进
|
124
|
+
self.current_step = (self.current_step + 1) % len(self.gradient)
|
125
|
+
|
126
|
+
# 50ms后继续下一帧 (约20FPS)
|
127
|
+
self.root.after(50, self.animate_gradient)
|
128
|
+
|
129
|
+
def reset_animation(self):
|
130
|
+
"""重置动画状态"""
|
131
|
+
self.is_animating = False
|
132
|
+
self.current_step = 0
|
133
|
+
self.start_button.config(text="开始渐变")
|
134
|
+
self.label.config(background='SystemButtonFace') # 恢复默认背景色
|
135
|
+
|
136
|
+
|
137
|
+
if __name__ == "__main__":
|
138
|
+
root = tk.Tk()
|
139
|
+
app = GradientLabelApp(root)
|
140
|
+
root.mainloop()
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from tkflu import *
|
2
|
+
|
3
|
+
|
4
|
+
root = FluWindow()
|
5
|
+
|
6
|
+
theme_manager = FluThemeManager(root)
|
7
|
+
|
8
|
+
menubar = FluMenuBar(root)
|
9
|
+
menubar.add_command(label="Item1", width=80, command=lambda: print("FluMenu1 -> Clicked"))
|
10
|
+
menubar.show()
|
11
|
+
|
12
|
+
button = FluToggleButton(
|
13
|
+
text="Toggle Theme", command=lambda: toggle_theme(button, theme_manager)
|
14
|
+
)
|
15
|
+
button.pack(padx=3, pady=3, )
|
16
|
+
|
17
|
+
button2 = FluToggleButton(
|
18
|
+
text="Toggle Button"
|
19
|
+
)
|
20
|
+
button2.pack(padx=3, pady=3, )
|
21
|
+
|
22
|
+
root.mainloop()
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class FluGradient:
|
2
|
+
def hex_to_rgb(self, h: str):
|
3
|
+
h = h.lstrip('#')
|
4
|
+
return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
|
5
|
+
|
6
|
+
def rgb_to_hex(self, rgb):
|
7
|
+
return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"
|
8
|
+
|
9
|
+
def generate_rgb2hex(self, start_color, end_color, steps):
|
10
|
+
"""生成颜色渐变序列"""
|
11
|
+
import numpy as np
|
12
|
+
gradient = []
|
13
|
+
for t in np.linspace(0, 1, steps):
|
14
|
+
r = int(start_color[0] + (end_color[0] - start_color[0]) * t)
|
15
|
+
g = int(start_color[1] + (end_color[1] - start_color[1]) * t)
|
16
|
+
b = int(start_color[2] + (end_color[2] - start_color[2]) * t)
|
17
|
+
gradient.append(f"#{r:02x}{g:02x}{b:02x}")
|
18
|
+
return gradient
|
19
|
+
|
20
|
+
def generate_hex2hex(self, start_hex, end_hex, steps):
|
21
|
+
"""
|
22
|
+
专为HEX颜色设计的渐变生成器
|
23
|
+
:param start_hex: 起始颜色 HEX格式 (如 "#FF0000")
|
24
|
+
:param end_hex: 结束颜色 HEX格式 (如 "#0000FF")
|
25
|
+
:param steps: 渐变步数
|
26
|
+
:return: HEX格式的颜色列表
|
27
|
+
"""
|
28
|
+
|
29
|
+
# 去除#号并转换为RGB元组
|
30
|
+
|
31
|
+
# RGB转HEX
|
32
|
+
|
33
|
+
rgb_start = self.hex_to_rgb(start_hex)
|
34
|
+
rgb_end = self.hex_to_rgb(end_hex)
|
35
|
+
import numpy as np
|
36
|
+
gradient = []
|
37
|
+
for t in np.linspace(0, 1, steps):
|
38
|
+
# 计算每个通道的中间值
|
39
|
+
r = int(rgb_start[0] + (rgb_end[0] - rgb_start[0]) * t)
|
40
|
+
g = int(rgb_start[1] + (rgb_end[1] - rgb_start[1]) * t)
|
41
|
+
b = int(rgb_start[2] + (rgb_end[2] - rgb_start[2]) * t)
|
42
|
+
|
43
|
+
# 确保值在0-255范围内并转换为HEX
|
44
|
+
gradient.append(
|
45
|
+
self.rgb_to_hex(
|
46
|
+
(
|
47
|
+
max(0, min(255, r)),
|
48
|
+
max(0, min(255, g)),
|
49
|
+
max(0, min(255, b))
|
50
|
+
)
|
51
|
+
)
|
52
|
+
)
|
53
|
+
|
54
|
+
return gradient
|
@@ -1,8 +1,9 @@
|
|
1
1
|
from tkinter import Frame, Menu
|
2
2
|
from tkdeft.object import DObject
|
3
|
+
from .designs.gradient import FluGradient
|
3
4
|
|
4
5
|
|
5
|
-
class FluMenuBar(Frame, DObject):
|
6
|
+
class FluMenuBar(Frame, DObject, FluGradient):
|
6
7
|
def __init__(self, *args, mode="light", height=40, **kwargs):
|
7
8
|
self._init(mode)
|
8
9
|
|
@@ -26,6 +27,9 @@ class FluMenuBar(Frame, DObject):
|
|
26
27
|
|
27
28
|
self.theme(mode=mode)
|
28
29
|
|
30
|
+
def show(self):
|
31
|
+
self.pack(fill="x")
|
32
|
+
|
29
33
|
def add_command(self, custom_widget=None, width=40, **kwargs):
|
30
34
|
if custom_widget:
|
31
35
|
widget = custom_widget(self)
|
@@ -103,6 +107,16 @@ class FluMenuBar(Frame, DObject):
|
|
103
107
|
def action(self, id):
|
104
108
|
return self.dcget("actions")[id]
|
105
109
|
|
110
|
+
def update_children(self):
|
111
|
+
actions = self.dcget("actions")
|
112
|
+
for key in actions:
|
113
|
+
widget = actions[key]
|
114
|
+
if hasattr(widget, "theme"):
|
115
|
+
widget.theme(mode=self.mode)
|
116
|
+
if hasattr(widget, "_draw"):
|
117
|
+
widget._draw()
|
118
|
+
widget.update()
|
119
|
+
|
106
120
|
def theme(self, mode="light"):
|
107
121
|
self.theme_myself(mode=mode)
|
108
122
|
|
@@ -116,22 +130,30 @@ class FluMenuBar(Frame, DObject):
|
|
116
130
|
widget._draw()
|
117
131
|
widget.update()
|
118
132
|
|
119
|
-
def theme_myself(self, mode="light"):
|
133
|
+
def theme_myself(self, mode="light", animate_steps: int = 10):
|
134
|
+
from .designs.menubar import menubar
|
135
|
+
m = menubar(mode)
|
120
136
|
self.mode = mode
|
121
137
|
if mode.lower() == "dark":
|
122
|
-
self
|
138
|
+
if hasattr(self, "tk"):
|
139
|
+
back_colors = self.generate_hex2hex(self.attributes.back_color, m["back_color"], steps=10)
|
140
|
+
for i in range(10):
|
141
|
+
def update(ii=i): # 使用默认参数立即捕获i的值
|
142
|
+
self.dconfigure(back_color=back_colors[ii])
|
143
|
+
self._draw()
|
144
|
+
|
145
|
+
self.after(i * 10, update) # 直接传递函数,不需要lambda
|
146
|
+
self.after(animate_steps*10+50, lambda: self.update_children())
|
123
147
|
else:
|
124
|
-
self
|
148
|
+
if hasattr(self, "tk"):
|
149
|
+
back_colors = self.generate_hex2hex(self.attributes.back_color, m["back_color"], steps=10)
|
150
|
+
for i in range(10):
|
151
|
+
def update(ii=i): # 使用默认参数立即捕获i的值
|
152
|
+
self.dconfigure(back_color=back_colors[ii])
|
153
|
+
self._draw()
|
125
154
|
|
126
|
-
|
127
|
-
self.dconfigure(
|
128
|
-
back_color="#f3f3f3"
|
129
|
-
)
|
155
|
+
self.after(i * 20, update) # 直接传递函数,不需要lambda
|
130
156
|
|
131
|
-
def _dark(self):
|
132
|
-
self.dconfigure(
|
133
|
-
back_color="#202020"
|
134
|
-
)
|
135
157
|
|
136
158
|
def _draw(self, event=None):
|
137
159
|
self.config(background=self.attributes.back_color)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from easydict import EasyDict
|
1
2
|
from tkdeft.windows.draw import DSvgDraw
|
2
3
|
from tkdeft.windows.canvas import DCanvas
|
3
4
|
from tkdeft.windows.drawwidget import DDrawWidget
|
@@ -60,9 +61,10 @@ class FluToggleButtonCanvas(DCanvas):
|
|
60
61
|
|
61
62
|
|
62
63
|
from .tooltip import FluToolTipBase
|
64
|
+
from .designs.gradient import FluGradient
|
63
65
|
|
64
66
|
|
65
|
-
class FluToggleButton(FluToggleButtonCanvas, DDrawWidget, FluToolTipBase):
|
67
|
+
class FluToggleButton(FluToggleButtonCanvas, DDrawWidget, FluToolTipBase, FluGradient):
|
66
68
|
def __init__(self, *args,
|
67
69
|
text="",
|
68
70
|
width=120,
|
@@ -117,7 +119,7 @@ class FluToggleButton(FluToggleButtonCanvas, DDrawWidget, FluToolTipBase):
|
|
117
119
|
|
118
120
|
self.theme(mode=mode)
|
119
121
|
|
120
|
-
def _draw(self, event=None):
|
122
|
+
def _draw(self, event=None, tempcolor: dict = None):
|
121
123
|
super()._draw(event)
|
122
124
|
|
123
125
|
width = self.winfo_width()
|
@@ -128,39 +130,49 @@ class FluToggleButton(FluToggleButtonCanvas, DDrawWidget, FluToolTipBase):
|
|
128
130
|
state = self.dcget("state")
|
129
131
|
|
130
132
|
_dict = None
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
if not tempcolor:
|
134
|
+
if not self.attributes.checked:
|
135
|
+
if state == "normal":
|
136
|
+
if self.enter:
|
137
|
+
if self.button1:
|
138
|
+
_dict = self.attributes.uncheck.pressed
|
139
|
+
else:
|
140
|
+
_dict = self.attributes.uncheck.hover
|
137
141
|
else:
|
138
|
-
_dict = self.attributes.uncheck.
|
142
|
+
_dict = self.attributes.uncheck.rest
|
139
143
|
else:
|
140
|
-
_dict = self.attributes.uncheck.
|
144
|
+
_dict = self.attributes.uncheck.disabled
|
141
145
|
else:
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
146
|
+
if state == "normal":
|
147
|
+
if self.enter:
|
148
|
+
if self.button1:
|
149
|
+
_dict = self.attributes.check.pressed
|
150
|
+
else:
|
151
|
+
_dict = self.attributes.check.hover
|
148
152
|
else:
|
149
|
-
_dict = self.attributes.check.
|
153
|
+
_dict = self.attributes.check.rest
|
150
154
|
else:
|
151
|
-
_dict = self.attributes.check.
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
155
|
+
_dict = self.attributes.check.disabled
|
156
|
+
|
157
|
+
_back_color = _dict.back_color
|
158
|
+
_back_opacity = _dict.back_opacity
|
159
|
+
_border_color = _dict.border_color
|
160
|
+
_border_color_opacity = _dict.border_color_opacity
|
161
|
+
_border_color2 = _dict.border_color2
|
162
|
+
_border_color2_opacity = _dict.border_color2_opacity
|
163
|
+
_border_width = _dict.border_width
|
164
|
+
_radius = _dict.radius
|
165
|
+
_text_color = _dict.text_color
|
166
|
+
else:
|
167
|
+
_back_color = tempcolor.back_color
|
168
|
+
_back_opacity = tempcolor.back_opacity
|
169
|
+
_border_color = tempcolor.border_color
|
170
|
+
_border_color_opacity = tempcolor.border_color_opacity
|
171
|
+
_border_color2 = tempcolor.border_color2
|
172
|
+
_border_color2_opacity = tempcolor.border_color2_opacity
|
173
|
+
_border_width = tempcolor.border_width
|
174
|
+
_radius = tempcolor.radius
|
175
|
+
_text_color = tempcolor.text_color
|
164
176
|
|
165
177
|
self.element_border = self.create_round_rectangle_with_text(
|
166
178
|
0, 0, width, height, _radius, temppath=self.temppath,
|
@@ -379,9 +391,90 @@ class FluToggleButton(FluToggleButtonCanvas, DDrawWidget, FluToolTipBase):
|
|
379
391
|
def invoke(self):
|
380
392
|
self.attributes.command()
|
381
393
|
|
382
|
-
def toggle(self):
|
394
|
+
def toggle(self, animate_steps: int = 10):
|
395
|
+
"""
|
396
|
+
|
397
|
+
"back_color": "#ffffff",
|
398
|
+
"back_opacity": "0.7",
|
399
|
+
"border_color": "#000000",
|
400
|
+
"border_color_opacity": "0.2",
|
401
|
+
"border_color2": "#000000",
|
402
|
+
"border_color2_opacity": "0.3",
|
403
|
+
"border_width": 1,
|
404
|
+
"radius": 6,
|
405
|
+
"text_color": "#000000",
|
406
|
+
:return:
|
407
|
+
"""
|
408
|
+
steps = animate_steps
|
409
|
+
check = self.attributes.check
|
410
|
+
uncheck = self.attributes.uncheck
|
411
|
+
if uncheck.pressed.border_color2 is None:
|
412
|
+
uncheck.pressed.border_color2 = uncheck.pressed.border_color
|
413
|
+
if check.pressed.border_color2 is None:
|
414
|
+
check.pressed.border_color2 = check.pressed.border_color
|
415
|
+
if uncheck.pressed.border_color2_opacity is None:
|
416
|
+
uncheck.pressed.border_color2_opacity = uncheck.pressed.border_color_opacity
|
417
|
+
if check.pressed.border_color2_opacity is None:
|
418
|
+
check.pressed.border_color2_opacity = check.pressed.border_color_opacity
|
383
419
|
if self.attributes.checked:
|
384
420
|
self.attributes.checked = False
|
421
|
+
back_colors = self.generate_hex2hex(
|
422
|
+
check.pressed.back_color, uncheck.rest.back_color, steps
|
423
|
+
)
|
424
|
+
border_colors = self.generate_hex2hex(
|
425
|
+
check.pressed.border_color, uncheck.rest.border_color, steps
|
426
|
+
)
|
427
|
+
border_colors2 = self.generate_hex2hex(
|
428
|
+
check.pressed.border_color2, uncheck.rest.border_color2, steps
|
429
|
+
)
|
430
|
+
text_colors = self.generate_hex2hex(
|
431
|
+
check.pressed.text_color, uncheck.rest.text_color, steps
|
432
|
+
)
|
433
|
+
import numpy as np
|
434
|
+
back_opacitys = np.linspace(
|
435
|
+
float(check.pressed.back_opacity), float(uncheck.rest.back_opacity), steps).tolist()
|
436
|
+
border_color_opacitys = np.linspace(
|
437
|
+
float(check.pressed.border_color_opacity), float(uncheck.rest.border_color_opacity), steps).tolist()
|
438
|
+
border_color2_opacitys = np.linspace(
|
439
|
+
float(check.pressed.border_color2_opacity), float(uncheck.rest.border_color2_opacity), steps).tolist()
|
385
440
|
else:
|
386
441
|
self.attributes.checked = True
|
387
|
-
|
442
|
+
back_colors = self.generate_hex2hex(
|
443
|
+
uncheck.pressed.back_color, check.rest.back_color, steps
|
444
|
+
)
|
445
|
+
border_colors = self.generate_hex2hex(
|
446
|
+
uncheck.pressed.back_color, check.rest.back_color, steps
|
447
|
+
)
|
448
|
+
border_colors2 = self.generate_hex2hex(
|
449
|
+
uncheck.pressed.border_color2, check.rest.border_color2, steps
|
450
|
+
)
|
451
|
+
text_colors = self.generate_hex2hex(
|
452
|
+
uncheck.pressed.text_color, check.rest.text_color, steps
|
453
|
+
)
|
454
|
+
import numpy as np
|
455
|
+
back_opacitys = np.linspace(float(uncheck.pressed.back_opacity), float(check.rest.back_opacity),
|
456
|
+
steps).tolist()
|
457
|
+
border_color_opacitys = np.linspace(float(uncheck.pressed.border_color_opacity), float(check.rest.border_color_opacity),
|
458
|
+
steps).tolist()
|
459
|
+
border_color2_opacitys = np.linspace(float(uncheck.pressed.border_color2_opacity),
|
460
|
+
float(check.rest.border_color2_opacity),
|
461
|
+
steps).tolist()
|
462
|
+
for i in range(steps):
|
463
|
+
def update(ii=i):
|
464
|
+
from easydict import EasyDict
|
465
|
+
tempcolor = EasyDict(
|
466
|
+
{
|
467
|
+
"back_color": back_colors[ii],
|
468
|
+
"back_opacity": back_opacitys[ii],
|
469
|
+
"border_color": border_colors[ii],
|
470
|
+
"border_color_opacity": str(border_color_opacitys[ii]),
|
471
|
+
"border_color2": border_colors2[ii],
|
472
|
+
"border_color2_opacity": str(border_color2_opacitys[ii]),
|
473
|
+
"border_width": 1,
|
474
|
+
"text_color": text_colors[ii],
|
475
|
+
"radius": 6,
|
476
|
+
}
|
477
|
+
)
|
478
|
+
self._draw(None, tempcolor)
|
479
|
+
self.after(i*10, update)
|
480
|
+
self.after(steps*10+10, lambda: self._draw(None, None))
|
@@ -66,7 +66,7 @@ class FluToolTip(FluPopupWindow):
|
|
66
66
|
background=n["back_color"]
|
67
67
|
)
|
68
68
|
self.wm_attributes("-transparentcolor", n["back_color"])
|
69
|
-
print(n["back_color"])
|
69
|
+
#print(n["back_color"])
|
70
70
|
if hasattr(self, "_frame"):
|
71
71
|
self._frame.dconfigure(
|
72
72
|
back_color=n["frame_color"],
|
@@ -128,7 +128,7 @@ class FluToolTip2(FluPopupWindow):
|
|
128
128
|
background=n["back_color"]
|
129
129
|
)
|
130
130
|
self.wm_attributes("-transparentcolor", n["back_color"])
|
131
|
-
print(n["back_color"])
|
131
|
+
#print(n["back_color"])
|
132
132
|
if hasattr(self, "_frame"):
|
133
133
|
self._frame.dconfigure(
|
134
134
|
back_color=n["frame_color"],
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|