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.
Files changed (55) hide show
  1. {tkfluent-0.0.9 → tkfluent-0.1.0}/PKG-INFO +2 -1
  2. {tkfluent-0.0.9 → tkfluent-0.1.0}/pyproject.toml +2 -1
  3. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/bwm.py +14 -1
  4. tkfluent-0.1.0/tkflu/demos/demo1.py +8 -0
  5. tkfluent-0.1.0/tkflu/demos/grad.py +70 -0
  6. tkfluent-0.1.0/tkflu/demos/grad2.py +140 -0
  7. tkfluent-0.1.0/tkflu/demos/grad3.py +22 -0
  8. tkfluent-0.1.0/tkflu/demos/test.py +8 -0
  9. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/demos/tooltip.py +1 -1
  10. tkfluent-0.1.0/tkflu/designs/gradient.py +54 -0
  11. tkfluent-0.1.0/tkflu/designs/menubar.py +13 -0
  12. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/frame.py +2 -0
  13. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/menu.py +1 -1
  14. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/menubar.py +34 -12
  15. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/togglebutton.py +125 -32
  16. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/tooltip.py +2 -2
  17. {tkfluent-0.0.9 → tkfluent-0.1.0}/README.md +0 -0
  18. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/__init__.py +0 -0
  19. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/__main__.py +0 -0
  20. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/badge.py +0 -0
  21. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/button.py +0 -0
  22. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/checkbox.py +0 -0
  23. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/constants.py +0 -0
  24. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/customwindow.py +0 -0
  25. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/customwindow2.py +0 -0
  26. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/defs.py +0 -0
  27. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/demos/__init__.py +0 -0
  28. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/demos/acrylic1.py +0 -0
  29. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/__init__.py +0 -0
  30. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/badge.py +0 -0
  31. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/button.py +0 -0
  32. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/design.py +0 -0
  33. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/entry.py +0 -0
  34. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/fonts/__init__.py +0 -0
  35. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/fonts/segoeui.ttf +0 -0
  36. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/frame.py +0 -0
  37. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/primary_color.py +0 -0
  38. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/slider.py +0 -0
  39. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/text.py +0 -0
  40. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/tooltip.py +0 -0
  41. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/designs/window.py +0 -0
  42. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/entry.py +0 -0
  43. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/icons.py +0 -0
  44. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/image.py +0 -0
  45. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/label.py +0 -0
  46. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/listbox.py +0 -0
  47. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/litenav.py +0 -0
  48. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/popupmenu.py +0 -0
  49. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/popupwindow.py +0 -0
  50. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/scrollbar.py +0 -0
  51. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/slider.py +0 -0
  52. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/text.py +0 -0
  53. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/thememanager.py +0 -0
  54. {tkfluent-0.0.9 → tkfluent-0.1.0}/tkflu/toplevel.py +0 -0
  55. {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.9
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.9"
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
- class BWm(object):
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,8 @@
1
+ from tkflu import *
2
+
3
+
4
+ root = FluWindow()
5
+
6
+ root.after(1000, lambda: root.theme("dark"))
7
+
8
+ root.mainloop()
@@ -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,8 @@
1
+ import numpy as np
2
+
3
+ float1 = 1.0
4
+ float2 = 5.0
5
+ steps = 10 # 生成 10 个点
6
+
7
+ floats = np.linspace(float1, float2, steps).tolist()
8
+ print(floats)
@@ -3,7 +3,7 @@ from tkflu import *
3
3
 
4
4
  root = FluWindow()
5
5
 
6
- thememanager = FluThemeManager(root, mode="dark")
6
+ thememanager = FluThemeManager(root, mode="light")
7
7
 
8
8
  button = FluButton(root, text="Click me", command=lambda: print("Clicked"), style="standard")
9
9
  button.pack()
@@ -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
@@ -0,0 +1,13 @@
1
+ from .primary_color import get_primary_color
2
+
3
+
4
+ def menubar(mode):
5
+ mode = mode.lower()
6
+ if mode == "light":
7
+ return {
8
+ "back_color": "#f3f3f3",
9
+ }
10
+ else:
11
+ return {
12
+ "back_color": "#202020",
13
+ }
@@ -188,6 +188,8 @@ class FluFrame(Frame, DObject):
188
188
  border_width=n["border_width"],
189
189
  radius=n["radius"],
190
190
  )
191
+ self._draw()
192
+ self.canvas.update()
191
193
 
192
194
  def _light(self):
193
195
  self._theme("light", "standard")
@@ -86,7 +86,7 @@ class FluMenu(FluPopupMenu, FluToolTipBase):
86
86
  id = widget._w
87
87
 
88
88
  def command(event=None):
89
- print(menu._w)
89
+ #print(menu._w)
90
90
 
91
91
  menu.popup(widget.winfo_rootx()+widget.winfo_width()+100, widget.winfo_rooty())
92
92
  menu.window.deiconify()
@@ -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._dark()
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._light()
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
- def _light(self):
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
- if not self.attributes.checked:
133
- if state == "normal":
134
- if self.enter:
135
- if self.button1:
136
- _dict = self.attributes.uncheck.pressed
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.hover
142
+ _dict = self.attributes.uncheck.rest
139
143
  else:
140
- _dict = self.attributes.uncheck.rest
144
+ _dict = self.attributes.uncheck.disabled
141
145
  else:
142
- _dict = self.attributes.uncheck.disabled
143
- else:
144
- if state == "normal":
145
- if self.enter:
146
- if self.button1:
147
- _dict = self.attributes.check.pressed
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.hover
153
+ _dict = self.attributes.check.rest
150
154
  else:
151
- _dict = self.attributes.check.rest
152
- else:
153
- _dict = self.attributes.check.disabled
154
-
155
- _back_color = _dict.back_color
156
- _back_opacity = _dict.back_opacity
157
- _border_color = _dict.border_color
158
- _border_color_opacity = _dict.border_color_opacity
159
- _border_color2 = _dict.border_color2
160
- _border_color2_opacity = _dict.border_color2_opacity
161
- _border_width = _dict.border_width
162
- _radius = _dict.radius
163
- _text_color = _dict.text_color
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
- self._draw(None)
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