tkfluent 0.1.3__tar.gz → 0.1.4__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 (60) hide show
  1. {tkfluent-0.1.3 → tkfluent-0.1.4}/PKG-INFO +2 -2
  2. {tkfluent-0.1.3 → tkfluent-0.1.4}/pyproject.toml +2 -2
  3. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/__main__.py +7 -4
  4. tkfluent-0.1.4/tkflu/designs/scrollbar.py +56 -0
  5. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/slider.py +16 -0
  6. tkfluent-0.1.4/tkflu/popupwindow.py +66 -0
  7. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/slider.py +156 -87
  8. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/thememanager.py +11 -11
  9. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/tooltip.py +1 -6
  10. tkfluent-0.1.3/tkflu/popupwindow.py +0 -33
  11. {tkfluent-0.1.3 → tkfluent-0.1.4}/README.md +0 -0
  12. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/__init__.py +0 -0
  13. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/badge.py +0 -0
  14. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/button.py +0 -0
  15. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/bwm.py +0 -0
  16. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/checkbox.py +0 -0
  17. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/constants.py +0 -0
  18. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/customwindow.py +0 -0
  19. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/customwindow2.py +0 -0
  20. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/defs.py +0 -0
  21. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/__init__.py +0 -0
  22. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/acrylic1.py +0 -0
  23. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/demo1.py +0 -0
  24. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/designer.py +0 -0
  25. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/grad.py +0 -0
  26. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/grad2.py +0 -0
  27. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/grad3.py +0 -0
  28. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/test.py +0 -0
  29. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/demos/tooltip.py +0 -0
  30. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/__init__.py +0 -0
  31. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/animation.py +0 -0
  32. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/badge.py +0 -0
  33. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/button.py +0 -0
  34. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/design.py +0 -0
  35. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/entry.py +0 -0
  36. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/fonts/__init__.py +0 -0
  37. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/fonts/segoeui.ttf +0 -0
  38. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/frame.py +0 -0
  39. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/gradient.py +0 -0
  40. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/label.py +0 -0
  41. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/menubar.py +0 -0
  42. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/primary_color.py +0 -0
  43. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/text.py +0 -0
  44. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/tooltip.py +0 -0
  45. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/designs/window.py +0 -0
  46. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/entry.py +0 -0
  47. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/frame.py +0 -0
  48. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/icons.py +0 -0
  49. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/image.py +0 -0
  50. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/label.py +0 -0
  51. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/listbox.py +0 -0
  52. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/litenav.py +0 -0
  53. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/menu.py +0 -0
  54. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/menubar.py +0 -0
  55. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/popupmenu.py +0 -0
  56. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/scrollbar.py +0 -0
  57. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/text.py +0 -0
  58. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/togglebutton.py +0 -0
  59. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/toplevel.py +0 -0
  60. {tkfluent-0.1.3 → tkfluent-0.1.4}/tkflu/window.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: tkfluent
3
- Version: 0.1.3
3
+ Version: 0.1.4
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
@@ -30,7 +30,7 @@ Requires-Dist: easydict (>=1.13,<2.0)
30
30
  Requires-Dist: numpy
31
31
  Requires-Dist: pillow (>=10.2.0,<11.0.0)
32
32
  Requires-Dist: svgwrite (>=1.4.3,<2.0.0)
33
- Requires-Dist: tkdeft (==0.0.9)
33
+ Requires-Dist: tkdeft (==0.1.0)
34
34
  Requires-Dist: tkextrafont (>=0.6.3,<0.7.0)
35
35
  Requires-Dist: tksvg (>=0.7.4,<0.8.0)
36
36
  Project-URL: Documentation, https://tkfluent.netlify.app
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tkfluent"
3
- version = "0.1.3"
3
+ version = "0.1.4"
4
4
  description = "Fluent(SunValley) Design for Tkinter. Modern GUI"
5
5
  authors = ["XiangQinxi <xiangqinxi@outlook.com>"]
6
6
  readme = "README.md"
@@ -36,7 +36,7 @@ tksvg = "^0.7.4"
36
36
  tkextrafont = "^0.6.3"
37
37
  svgwrite = "^1.4.3"
38
38
  pillow = "^10.2.0"
39
- tkdeft = "0.0.9"
39
+ tkdeft = "0.1.0"
40
40
  easydict = "^1.13"
41
41
  numpy = "*"
42
42
 
@@ -4,7 +4,7 @@ from tkinter.font import *
4
4
 
5
5
  purple_primary_color()
6
6
  set_animation_steps(10)
7
- set_animation_step_time(10)
7
+ set_animation_step_time(12)
8
8
 
9
9
  def togglestate():
10
10
  if button1.dcget("state") == NORMAL:
@@ -23,7 +23,7 @@ def togglestate():
23
23
  entry1._draw()
24
24
  root = FluWindow()
25
25
  #root.wincustom(way=0)
26
- root.geometry("360x600")
26
+ root.geometry("360x650")
27
27
 
28
28
  popupmenu = FluPopupMenu()
29
29
 
@@ -108,7 +108,7 @@ entry1.pack(fill="x", padx=5, pady=5)
108
108
  text1 = FluText(frame)
109
109
  text1.pack(fill="x", padx=5, pady=5)
110
110
 
111
- slider1 = FluSlider(frame, value=0)
111
+ slider1 = FluSlider(frame, value=0, max=200)
112
112
  slider1.pack(fill="x", padx=5, pady=5)
113
113
 
114
114
  """listbox1 = FluListBox(frame)
@@ -116,5 +116,8 @@ listbox1.dconfigure()
116
116
  listbox1.pack(fill="x", padx=5, pady=5)"""
117
117
 
118
118
  frame.pack(fill="both", expand="yes", side="right", padx=15, pady=15)
119
- frame.update_idletasks()
119
+ #frame.update_idletasks()
120
+
121
+ #thememanager.mode("light")
122
+
120
123
  root.mainloop()
@@ -0,0 +1,56 @@
1
+ def scrollbar(mode, state=None):
2
+ """滚动栏设计配置"""
3
+ if mode.lower() == "dark":
4
+ return {
5
+ "rest": {
6
+ "track_color": "#202020",
7
+ "track_opacity": 0.5,
8
+ "thumb_color": "#606060",
9
+ "thumb_opacity": 0.8
10
+ },
11
+ "hover": {
12
+ "track_color": "#202020",
13
+ "track_opacity": 0.7,
14
+ "thumb_color": "#808080",
15
+ "thumb_opacity": 1.0
16
+ },
17
+ "pressed": {
18
+ "track_color": "#202020",
19
+ "track_opacity": 0.9,
20
+ "thumb_color": "#A0A0A0",
21
+ "thumb_opacity": 1.0
22
+ },
23
+ "disabled": {
24
+ "track_color": "#202020",
25
+ "track_opacity": 0.3,
26
+ "thumb_color": "#404040",
27
+ "thumb_opacity": 0.5
28
+ }
29
+ }
30
+ else: # light mode
31
+ return {
32
+ "rest": {
33
+ "track_color": "#F0F0F0",
34
+ "track_opacity": 0.5,
35
+ "thumb_color": "#C0C0C0",
36
+ "thumb_opacity": 0.8
37
+ },
38
+ "hover": {
39
+ "track_color": "#F0F0F0",
40
+ "track_opacity": 0.7,
41
+ "thumb_color": "#A0A0A0",
42
+ "thumb_opacity": 1.0
43
+ },
44
+ "pressed": {
45
+ "track_color": "#F0F0F0",
46
+ "track_opacity": 0.9,
47
+ "thumb_color": "#808080",
48
+ "thumb_opacity": 1.0
49
+ },
50
+ "disabled": {
51
+ "track_color": "#F0F0F0",
52
+ "track_opacity": 0.3,
53
+ "thumb_color": "#E0E0E0",
54
+ "thumb_opacity": 0.5
55
+ }
56
+ }
@@ -13,6 +13,8 @@ def slider(mode: str, state: str):
13
13
  "radius": 12,
14
14
  "inner_radius": 6,
15
15
 
16
+ "width": 28,
17
+
16
18
  "back_color": "#FFFFFF",
17
19
  "back_opacity": 1,
18
20
 
@@ -43,6 +45,8 @@ def slider(mode: str, state: str):
43
45
  "radius": 12,
44
46
  "inner_radius": 8,
45
47
 
48
+ "width": 28,
49
+
46
50
  "back_color": "#FFFFFF",
47
51
  "back_opacity": 1,
48
52
 
@@ -73,6 +77,8 @@ def slider(mode: str, state: str):
73
77
  "radius": 12,
74
78
  "inner_radius": 5,
75
79
 
80
+ "width": 28,
81
+
76
82
  "back_color": "#FFFFFF",
77
83
  "back_opacity": 1,
78
84
 
@@ -103,6 +109,8 @@ def slider(mode: str, state: str):
103
109
  "radius": 12,
104
110
  "inner_radius": 6,
105
111
 
112
+ "width": 28,
113
+
106
114
  "back_color": "#FFFFFF",
107
115
  "back_opacity": 1,
108
116
 
@@ -133,6 +141,8 @@ def slider(mode: str, state: str):
133
141
  "thumb": {
134
142
  "radius": 12,
135
143
 
144
+ "width": 28,
145
+
136
146
  "inner_radius": 6,
137
147
  "inner_back_color": get_primary_color()[1],
138
148
  "inner_back_opacity": 1,
@@ -164,6 +174,8 @@ def slider(mode: str, state: str):
164
174
  "thumb": {
165
175
  "radius": 12,
166
176
 
177
+ "width": 28,
178
+
167
179
  "inner_radius": 8,
168
180
  "inner_back_color": get_primary_color()[1],
169
181
  "inner_back_opacity": 1,
@@ -195,6 +207,8 @@ def slider(mode: str, state: str):
195
207
  "thumb": {
196
208
  "radius": 12,
197
209
 
210
+ "width": 28,
211
+
198
212
  "inner_radius": 5,
199
213
  "inner_back_color": get_primary_color()[1],
200
214
  "inner_back_opacity": 0.8,
@@ -226,6 +240,8 @@ def slider(mode: str, state: str):
226
240
  "thumb": {
227
241
  "radius": 12,
228
242
 
243
+ "width": 28,
244
+
229
245
  "inner_radius": 6,
230
246
  "inner_back_color": "#FFFFFF",
231
247
  "inner_back_opacity": 0.158100,
@@ -0,0 +1,66 @@
1
+ from tkinter import Toplevel
2
+
3
+
4
+ class FluPopupWindow(Toplevel):
5
+ def __init__(self, *args, transparent_color="#ebebeb", mode="light", width=100, height=46, custom=True, **kwargs):
6
+ super().__init__(*args, background=transparent_color, **kwargs)
7
+
8
+ self.theme(mode=mode)
9
+
10
+ if width > 0 and height > 0:
11
+ self.geometry(f"{width}x{height}")
12
+
13
+ if custom:
14
+ self.transient_color = transparent_color
15
+ self.overrideredirect(True)
16
+ self.wm_attributes("-transparentcolor", transparent_color)
17
+
18
+ self.withdraw()
19
+
20
+ self.bind("<FocusOut>", self._event_focusout, add="+")
21
+
22
+ def _event_focusout(self, event=None):
23
+ """self.wm_attributes("-alpha", 1)
24
+ self.deiconify()
25
+
26
+ from .designs.animation import get_animation_steps, get_animation_step_time
27
+
28
+ FRAMES_COUNT = get_animation_steps()
29
+ FRAME_DELAY = get_animation_step_time()
30
+
31
+ def fade_out(step=1):
32
+ alpha = step / FRAMES_COUNT # 按帧数变化,从0到1
33
+ self.wm_attributes("-alpha", alpha)
34
+ if step < FRAMES_COUNT:
35
+ # 每执行一次,增加一次透明度,间隔由帧数决定
36
+ self.after(int(round(FRAME_DELAY * FRAMES_COUNT / FRAMES_COUNT)), lambda: fade_out(step - 1))
37
+
38
+ fade_out() # 启动动画"""
39
+ self.withdraw()
40
+
41
+ def popup(self, x, y):
42
+ self.geometry(f"+{x}+{y}")
43
+ #self.focus_set()
44
+ self.wm_attributes("-alpha", 0.0)
45
+ self.deiconify()
46
+
47
+ from .designs.animation import get_animation_steps, get_animation_step_time
48
+
49
+ FRAMES_COUNT = get_animation_steps()
50
+ FRAME_DELAY = get_animation_step_time()
51
+
52
+ def fade_in(step=0):
53
+ alpha = step / FRAMES_COUNT # 按帧数变化,从0到1
54
+ self.wm_attributes("-alpha", alpha)
55
+ if step < FRAMES_COUNT:
56
+ # 每执行一次,增加一次透明度,间隔由帧数决定
57
+ self.after(int(round(FRAME_DELAY*FRAMES_COUNT / FRAMES_COUNT)), lambda: fade_in(step + 1))
58
+
59
+ fade_in() # 启动动画
60
+
61
+ def theme(self, mode=None):
62
+ if mode:
63
+ self.mode = mode
64
+ for widget in self.winfo_children():
65
+ if hasattr(widget, "theme"):
66
+ widget.theme(mode=self.mode.lower())
@@ -1,85 +1,75 @@
1
- from tkdeft.windows.draw import DSvgDraw
2
1
  from tkdeft.windows.canvas import DCanvas
2
+ from tkdeft.windows.draw import DSvgDraw
3
3
  from tkdeft.windows.drawwidget import DDrawWidget
4
4
 
5
5
  from .designs.slider import slider
6
6
 
7
7
 
8
8
  class FluSliderDraw(DSvgDraw):
9
- def create_slider(
9
+ def create_track(
10
10
  self,
11
- x1, y1, x2, y2,
12
- x3, # 滑块的x坐标
13
- r1, # 滑块外圆半径
14
- r2, # 滑块内圆半径
11
+ width, height, width2,
15
12
  temppath=None,
16
- fill="transparent", fill_opacity=1, # 滑块外圆的背景颜色、透明度
17
13
  radius=3, # 滑块进度条圆角大小
18
- outline="transparent", outline_opacity=1, # 滑块伪阴影的渐变色中的第一个渐变颜色、透明度
19
- outline2="transparent", outline2_opacity=1, # 滑块伪阴影的渐变色中的第二个渐变颜色、透明度
20
- inner_fill="transparent", inner_fill_opacity=1, # 滑块内圆的背景颜色、透明度
21
- track_fill="transparent", track_height=4, track_opacity=1, # 滑块进度条的选中部分矩形的背景颜色、高度、透明度
14
+ track_fill="transparent", track_opacity=1, # 滑块进度条的选中部分矩形的背景颜色、高度、透明度
22
15
  rail_fill="transparent", rail_opacity=1 #
23
16
  ):
24
- drawing = self.create_drawing(x2 - x1, y2 - y1, temppath=temppath, fill_opacity=0)
25
-
26
- border = drawing[1].linearGradient(start=(r1, 1), end=(r1, r1 * 2 - 1), id="DButton.Border",
27
- gradientUnits="userSpaceOnUse")
28
- border.add_stop_color(0.500208, outline, outline_opacity)
29
- border.add_stop_color(0.954545, outline2, outline2_opacity)
30
- drawing[1].defs.add(border)
31
- stroke = f"url(#{border.get_id()})"
32
- #print("x1:", x1, "\n", "y1:", y1, "\n", "x2:", x2, "\n", "y2:", y2, "\n", "r1:", r1, "\n", sep="")
33
-
34
- x = x1 + r1 - 4
35
- xx = x2 - r1 + 4
36
-
37
- #print("track_x1:", x, "\n", "track_x2:", xx, sep="")
38
-
39
- #print("")
17
+ drawing = self.create_drawing(width, height, temppath=temppath, fill_opacity=0)
40
18
 
41
19
  drawing[1].add(
42
20
  drawing[1].rect(
43
- (x, (y2 - y1) / 2 - track_height / 2),
44
- # 矩形x位置:画布最左的x坐标 + 滑块外半径 - 滑块内半径
45
- # 矩形y位置:画布高度(画布最上的y坐标 - 画布最上的y坐标)一半 - 进度条的高度的一半
46
- (xx - x, track_height),
47
- # 矩形宽度:画布最右的x坐标 - 滑块外半径 + 滑块内半径 | 矩形高度:进度条的高度
21
+ (0, 0), (width2, height),
48
22
  rx=radius,
49
- fill=rail_fill, fill_opacity=rail_opacity
23
+ fill=track_fill, fill_opacity=track_opacity, fill_rule="evenodd"
50
24
  )
51
- ) # 滑块进度未选中区域 (占全部)
25
+ ) # 滑块进度左边的选中区域 (只左部分)
52
26
 
53
27
  drawing[1].add(
54
28
  drawing[1].rect(
55
- (x, (y2 - y1) / 2 - track_height / 2),
56
- # 矩形x位置:画布最左的x坐标 + 滑块外半径 - 滑块内半径
57
- # 矩形y位置:画布高度(画布最上的y坐标 - 画布最上的y坐标)一半 - 进度条的高度的一半
58
- (x3 - x, track_height),
59
- # 矩形宽度:(滑块的x坐标 - 矩形x位置) | 矩形高度:进度条的高度
29
+ (width2, 0), (width-width2, height),
60
30
  rx=radius,
61
- fill=track_fill, fill_opacity=track_opacity, fill_rule="evenodd"
31
+ fill=rail_fill, fill_opacity=rail_opacity
62
32
  )
63
- ) # 滑块进度左边的选中区域 (只左部分)
33
+ ) # 滑块进度未选中区域 (占全部)
34
+
35
+ drawing[1].save()
36
+ return drawing[0]
37
+
38
+ def create_thumb(
39
+ self,
40
+ width, height,
41
+ r1, # 滑块外圆半径
42
+ r2, # 滑块内圆半径
43
+ temppath=None,
44
+ fill="transparent", fill_opacity=1, # 滑块外圆的背景颜色、透明度
45
+ outline="transparent", outline_opacity=1, # 滑块伪阴影的渐变色中的第一个渐变颜色、透明度
46
+ outline2="transparent", outline2_opacity=1, # 滑块伪阴影的渐变色中的第二个渐变颜色、透明度
47
+ inner_fill="transparent", inner_fill_opacity=1, # 滑块内圆的背景颜色、透明度
48
+ ):
49
+ drawing = self.create_drawing(width, height, temppath=temppath, fill_opacity=0)
64
50
 
65
- x = x3
66
- y = (y2 - y1) / 2
51
+ border = drawing[1].linearGradient(start=(r1, 1), end=(r1, r1 * 2 - 1), id="DButton.Border",
52
+ gradientUnits="userSpaceOnUse")
53
+ border.add_stop_color(0.500208, outline, outline_opacity)
54
+ border.add_stop_color(0.954545, outline2, outline2_opacity)
55
+ drawing[1].defs.add(border)
56
+ stroke = f"url(#{border.get_id()})"
67
57
 
68
58
  drawing[1].add(
69
59
  drawing[1].circle(
70
- (x, y), r1,
60
+ (width / 2, height / 2), r1,
71
61
  fill=stroke, fill_opacity=1, fill_rule="evenodd"
72
62
  )
73
63
  ) # 圆形滑块的伪阴影边框
74
64
  drawing[1].add(
75
65
  drawing[1].circle(
76
- (x, y), r1 - 1,
66
+ (width / 2, height / 2), r1 - 1,
77
67
  fill=fill, fill_opacity=fill_opacity, fill_rule="nonzero"
78
68
  )
79
69
  ) # 圆形滑块的外填充
80
70
  drawing[1].add(
81
71
  drawing[1].circle(
82
- (x, y), r2,
72
+ (width / 2, height / 2), r2,
83
73
  fill=inner_fill, fill_opacity=inner_fill_opacity, fill_rule="nonzero"
84
74
  )
85
75
  ) # 圆形滑块的内填充
@@ -90,23 +80,35 @@ class FluSliderDraw(DSvgDraw):
90
80
  class FluSliderCanvas(DCanvas):
91
81
  draw = FluSliderDraw
92
82
 
93
- def create_slider(self,
94
- x1, y1, x2, y2, x3, r1, r2, temppath=None,
95
- fill="transparent", fill_opacity=1, radius=3,
96
- outline="transparent", outline_opacity=1,
97
- outline2="transparent", outline2_opacity=1,
98
- inner_fill="transparent", inner_fill_opacity=1,
99
- track_fill="transparent", track_height=4, track_opacity=1,
100
- rail_fill="transparent", rail_opacity=1
101
- ):
102
- self._img = self.svgdraw.create_slider(
103
- x1, y1, x2, y2, x3, r1, r2, temppath=temppath,
104
- fill=fill, fill_opacity=fill_opacity, radius=radius,
83
+ def create_track(
84
+ self,
85
+ x1, y1, width, height, width2, temppath=None, radius=3,
86
+ track_fill="transparent", track_opacity=1,
87
+ rail_fill="transparent", rail_opacity=1
88
+ ):
89
+ self._img2 = self.svgdraw.create_track(
90
+ width, height, width2, temppath=temppath, radius=radius,
91
+ track_fill=track_fill, track_opacity=track_opacity,
92
+ rail_fill=rail_fill, rail_opacity=rail_opacity
93
+ )
94
+ self._tkimg2 = self.svgdraw.create_tksvg_image(self._img2)
95
+ #print(self._img2)
96
+ return self.create_image(x1, y1, anchor="nw", image=self._tkimg2)
97
+
98
+ def create_thumb(
99
+ self,
100
+ x1, y1, width, height, r1, r2, temppath=None,
101
+ fill="transparent", fill_opacity=1,
102
+ outline="transparent", outline_opacity=1,
103
+ outline2="transparent", outline2_opacity=1,
104
+ inner_fill="transparent", inner_fill_opacity=1,
105
+ ):
106
+ self._img = self.svgdraw.create_thumb(
107
+ width, height, r1, r2, temppath=temppath,
108
+ fill=fill, fill_opacity=fill_opacity,
105
109
  outline=outline, outline_opacity=outline_opacity,
106
110
  outline2=outline2, outline2_opacity=outline2_opacity,
107
111
  inner_fill=inner_fill, inner_fill_opacity=inner_fill_opacity,
108
- track_fill=track_fill, track_height=track_height, track_opacity=track_opacity,
109
- rail_fill=rail_fill, rail_opacity=rail_opacity
110
112
  )
111
113
  self._tkimg = self.svgdraw.create_tksvg_image(self._img)
112
114
  return self.create_image(x1, y1, anchor="nw", image=self._tkimg)
@@ -152,7 +154,9 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
152
154
 
153
155
  self.bind("<<Clicked>>", lambda event=None: self.focus_set(), add="+")
154
156
 
155
- self.bind("<Motion>", self._event_button1_motion)
157
+ self.bind("<B1-Motion>", self._event_button1_motion)
158
+
159
+ self.enter_thumb = False
156
160
 
157
161
  from .defs import set_default_font
158
162
  set_default_font(font, self.attributes)
@@ -192,6 +196,11 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
192
196
 
193
197
  #print("")
194
198
 
199
+ if hasattr(self, "_e1"):
200
+ self.tag_unbind(self.element_track, "<Enter>", self._e1)
201
+ if hasattr(self, "_e2"):
202
+ self.tag_unbind(self.element_track, "<Leave>", self._e2)
203
+
195
204
  self.delete("all")
196
205
 
197
206
  state = self.dcget("state")
@@ -200,13 +209,16 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
200
209
 
201
210
  if state == "normal":
202
211
  if event:
203
- if self.enter:
204
- if self.button1:
205
- _dict = self.attributes.pressed
212
+ if self.enter: # 先检查是否在组件内
213
+ if self.enter_thumb: # 再检查是否在滑块上
214
+ if self.button1:
215
+ _dict = self.attributes.pressed
216
+ else:
217
+ _dict = self.attributes.hover
206
218
  else:
207
- _dict = self.attributes.hover
219
+ _dict = self.attributes.hover # 在组件内但不在滑块上
208
220
  else:
209
- _dict = self.attributes.rest
221
+ _dict = self.attributes.rest # 不在组件内
210
222
  else:
211
223
  _dict = self.attributes.rest
212
224
  else:
@@ -224,6 +236,8 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
224
236
  _thumb_radius = _dict.thumb.radius
225
237
  _thumb_inner_radius = _dict.thumb.inner_radius
226
238
 
239
+ _thumb_width = _dict.thumb.width
240
+
227
241
  _thumb_back_color = _dict.thumb.back_color
228
242
  _thumb_back_opacity = _dict.thumb.back_opacity
229
243
 
@@ -237,34 +251,81 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
237
251
  _thumb_inner_back_opacity = _dict.thumb.inner_back_opacity
238
252
 
239
253
  thumb_xp = self.attributes.value / (self.attributes.max - self.attributes.min) # 滑块对应数值的比例
240
- thumb_x = (self.winfo_width() - (_thumb_radius + 4) * 2) * thumb_xp # 滑块对应数值的x左边
241
-
242
- self.attributes["^r"] = _thumb_radius # 滑块进度条x坐标
243
- self.attributes["^x"] = _thumb_radius - 4 # 滑块进度条
244
- self.attributes["^xx"] = self.winfo_width() - _thumb_radius + 4
254
+ thumb_x = self.winfo_width() * thumb_xp # 滑块对应数值的x左边
255
+
256
+ width = self.winfo_width()
257
+ height = self.winfo_height()
258
+ # 修改滑块位置计算
259
+ thumb_width = _thumb_width
260
+ min_x = thumb_width / 2
261
+ max_x = self.winfo_width() - thumb_width / 2
262
+ track_length = max_x - min_x
263
+
264
+ # 计算轨道实际可用宽度(减去滑块宽度)
265
+ effective_track_width = self.winfo_width() - thumb_width
266
+
267
+ thumb_xp = (self.attributes.value - self.attributes.min) / (self.attributes.max - self.attributes.min)
268
+ thumb_center = thumb_width / 2 + thumb_xp * effective_track_width
269
+
270
+ thumb_width = _thumb_width
271
+ effective_width = self.winfo_width() - thumb_width
272
+ ratio = (self.attributes.value - self.attributes.min) / (self.attributes.max - self.attributes.min)
273
+ thumb_left = thumb_width / 2 + ratio * effective_width - thumb_width / 2
274
+
275
+ # 确保不会超出右边界
276
+ thumb_left = min(thumb_left, self.winfo_width() - thumb_width)
277
+
278
+ # 创建轨道时,width2 参数应为选中部分的宽度(滑块中心位置)
279
+ self.element_track = self.create_track(
280
+ _thumb_width / 4,
281
+ height / 2 - _track_height,
282
+ self.winfo_width() - _thumb_width / 2,
283
+ _track_height,
284
+ thumb_center - _thumb_width / 4, # 关键修正:使用滑块中心相对于轨道起点的距离
285
+ temppath=self.temppath, radius=_radius,
286
+ track_fill=_track_back_color, track_opacity=_track_back_opacity,
287
+ rail_fill=_rail_back_color, rail_opacity=_rail_back_opacity
288
+ )
245
289
 
246
- self.element_thumb = self.create_slider(
247
- 0, 0, self.winfo_width(), self.winfo_height(), thumb_x, _thumb_radius, _thumb_inner_radius,
248
- temppath=self.temppath,
249
- fill=_thumb_back_color, fill_opacity=_thumb_back_opacity, radius=_radius,
290
+ self.element_thumb = self.create_thumb(
291
+ thumb_left, 0, # 直接使用计算出的左上角位置
292
+ thumb_width, thumb_width,
293
+ _thumb_radius, _thumb_inner_radius,
294
+ temppath=self.temppath2, fill=_thumb_back_color, fill_opacity=_thumb_back_opacity,
250
295
  outline=_thumb_border_color, outline_opacity=_thumb_border_color_opacity,
251
296
  outline2=_thumb_border_color2, outline2_opacity=_thumb_border_color2_opacity,
252
297
  inner_fill=_thumb_inner_back_color, inner_fill_opacity=_thumb_inner_back_opacity,
253
- track_height=_track_height, track_fill=_track_back_color, track_opacity=_track_back_opacity,
254
- rail_fill=_rail_back_color, rail_opacity=_rail_back_opacity
255
298
  )
256
299
 
300
+ self._e1 = self.tag_bind(self.element_thumb, "<Enter>", self._event_enter_thumb, add="+")
301
+ self._e2 = self.tag_bind(self.element_thumb, "<Leave>", self._event_leave_thumb, add="+")
302
+
257
303
  def pos(self, event):
258
- if self.enter:
259
- if self.button1:
260
- valuep = (event.x - self.attributes["^x"]) / (self.attributes["^xx"] - self.attributes["^x"]) # 数值的比例:(鼠标点击的x坐标 - 滑块进度条的x坐标) ÷ 滑块进度条的宽度
261
- value = (event.x - self.attributes["max"] - self.attributes["min"]) # 数值的比例 × 数值范围(最大数值 - 最小数值)
262
- value = ((event.x + self.attributes["^r"]) / (self.winfo_width())) * self.attributes.max
263
- self.dconfigure(
264
- value=value
265
- )
266
- #print("value:", value, sep="")
267
- #print("")
304
+ #print(event.x, event.y)
305
+ #if self.enter and self.button1:
306
+ # 获取滑块宽度
307
+ thumb_width = self.attributes.pressed.thumb.width
308
+
309
+ # 计算有效轨道长度
310
+ effective_width = self.winfo_width() - thumb_width
311
+
312
+ # 计算滑块位置比例(考虑滑块宽度边界)
313
+ ratio = (event.x - thumb_width/2) / effective_width
314
+ ratio = max(0, min(1, ratio)) # 限制在0-1范围内
315
+
316
+ # 计算实际值
317
+ value = self.attributes.min + ratio * (self.attributes.max - self.attributes.min)
318
+ self.dconfigure(value=value)
319
+ self._draw()
320
+ #print(self.focus_get())
321
+
322
+
323
+ def _event_enter_thumb(self, event=None):
324
+ self.enter_thumb = True
325
+ self.update()
326
+
327
+ def _event_leave_thumb(self, event=None):
328
+ self.enter_thumb = False
268
329
 
269
330
  def _event_button1_motion(self, event):
270
331
  self.pos(event)
@@ -293,6 +354,8 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
293
354
  "radius": r["thumb"]["radius"],
294
355
  "inner_radius": r["thumb"]["inner_radius"],
295
356
 
357
+ "width": r["thumb"]["width"],
358
+
296
359
  "back_color": r["thumb"]["back_color"],
297
360
  "back_opacity": r["thumb"]["back_opacity"],
298
361
 
@@ -320,6 +383,8 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
320
383
  "radius": h["thumb"]["radius"],
321
384
  "inner_radius": h["thumb"]["inner_radius"],
322
385
 
386
+ "width": r["thumb"]["width"],
387
+
323
388
  "back_color": h["thumb"]["back_color"],
324
389
  "back_opacity": h["thumb"]["back_opacity"],
325
390
 
@@ -347,6 +412,8 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
347
412
  "radius": p["thumb"]["radius"],
348
413
  "inner_radius": p["thumb"]["inner_radius"],
349
414
 
415
+ "width": r["thumb"]["width"],
416
+
350
417
  "back_color": p["thumb"]["back_color"],
351
418
  "back_opacity": p["thumb"]["back_opacity"],
352
419
 
@@ -374,6 +441,8 @@ class FluSlider(FluSliderCanvas, DDrawWidget):
374
441
  "radius": d["thumb"]["radius"],
375
442
  "inner_radius": d["thumb"]["inner_radius"],
376
443
 
444
+ "width": r["thumb"]["width"],
445
+
377
446
  "back_color": d["thumb"]["back_color"],
378
447
  "back_opacity": d["thumb"]["back_opacity"],
379
448
 
@@ -11,17 +11,18 @@ class FluThemeManager(object):
11
11
  from tkinter import _default_root
12
12
  self._window = _default_root
13
13
  self._mode = mode
14
- self.mode(self._mode)
15
- self._window.after(delay, lambda: self.mode(self._mode))
14
+ #self.mode(self._mode)
15
+ #self._window.after(delay, lambda: self.mode(self._mode))
16
16
 
17
- def mode(self, mode: str, delay: Union[int, None] = 50):
18
- def _():
17
+ def mode(self, mode: str, delay: Union[int, None] = None):
18
+ def update_window():
19
19
  self._mode = mode
20
20
  if hasattr(self._window, "theme"):
21
21
  self._window.theme(mode=mode)
22
22
  if hasattr(self._window, "_draw"):
23
23
  self._window._draw()
24
24
  self._window.update()
25
+ def update_children():
25
26
  for widget in self._window.winfo_children():
26
27
  if hasattr(widget, "theme"):
27
28
  widget.theme(mode=mode)
@@ -30,19 +31,18 @@ class FluThemeManager(object):
30
31
  if hasattr(widget, "update_children"):
31
32
  widget.update_children()
32
33
  #widget.update()
33
- if not delay == 0:
34
- self._window.after(delay, _)
35
- else:
36
- _()
37
- def __():
34
+ update_window()
35
+ update_children()
36
+
37
+ def update_children2():
38
38
  for widget in self._window.winfo_children():
39
39
  if hasattr(widget, "_draw"):
40
40
  widget._draw()
41
41
  if hasattr(widget, "update_children"):
42
42
  widget.update_children()
43
43
  widget.update()
44
- #print(len(self._window.winfo_children()))
45
- self._window.after(delay+len(self._window.winfo_children()), __)
44
+
45
+ #self._window.after(len(self._window.winfo_children())*50, update_children2)
46
46
 
47
47
  def toggle(self, delay: Union[int, None] = None):
48
48
  if self._mode == "light":
@@ -40,10 +40,6 @@ class FluToolTip(FluPopupWindow):
40
40
  self.wm_attributes("-alpha", 0.0)
41
41
  self.deiconify()
42
42
 
43
- # 设置初始透明度为0
44
-
45
-
46
- # 渐显动画
47
43
  def fade_in(step=0):
48
44
  FRAMES_COUNT = 20
49
45
  alpha = step / FRAMES_COUNT # 按帧数变化,从0到1
@@ -131,8 +127,7 @@ class FluToolTip2(FluPopupWindow):
131
127
  background=n["back_color"]
132
128
  )
133
129
 
134
- if sys.platform == "win32": # Only Windows supports the transparentcolor attribute
135
- self.wm_attributes("-transparentcolor", n["back_color"])
130
+ self.wm_attributes("-transparentcolor", n["back_color"])
136
131
  #print(n["back_color"])
137
132
  if hasattr(self, "_frame"):
138
133
  self._frame.dconfigure(
@@ -1,33 +0,0 @@
1
- from tkinter import Toplevel
2
-
3
-
4
- class FluPopupWindow(Toplevel):
5
- def __init__(self, *args, transparent_color="#ebebeb", mode="light", width=100, height=46, custom=True, **kwargs):
6
- super().__init__(*args, background=transparent_color, **kwargs)
7
-
8
- self.theme(mode=mode)
9
-
10
- self.geometry(f"{width}x{height}")
11
-
12
- if custom:
13
- self.transient_color = transparent_color
14
- self.overrideredirect(True)
15
- self.wm_attributes("-transparentcolor", transparent_color)
16
-
17
- self.withdraw()
18
-
19
- self.bind("<FocusOut>", self._event_focusout, add="+")
20
-
21
- def _event_focusout(self, event=None):
22
- self.withdraw()
23
-
24
- def popup(self, x, y):
25
- self.geometry(f"+{x}+{y}")
26
- #self.focus_set()
27
-
28
- def theme(self, mode=None):
29
- if mode:
30
- self.mode = mode
31
- for widget in self.winfo_children():
32
- if hasattr(widget, "theme"):
33
- widget.theme(mode=self.mode.lower())
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