tkfluent 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl
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.
- tkflu/__init__.py +3 -1
- tkflu/__main__.py +8 -5
- tkflu/button.py +188 -92
- tkflu/bwm.py +10 -7
- tkflu/demos/grad2.py +1 -1
- tkflu/designs/scrollbar.py +56 -0
- tkflu/designs/slider.py +16 -0
- tkflu/frame.py +11 -11
- tkflu/image.py +4 -0
- tkflu/label.py +8 -6
- tkflu/menubar.py +24 -17
- tkflu/popupwindow.py +34 -1
- tkflu/slider.py +156 -87
- tkflu/text.py +34 -2
- tkflu/thememanager.py +14 -13
- tkflu/togglebutton.py +76 -70
- tkflu/tooltip.py +9 -9
- {tkfluent-0.1.2.dist-info → tkfluent-0.1.4.dist-info}/METADATA +13 -5
- {tkfluent-0.1.2.dist-info → tkfluent-0.1.4.dist-info}/RECORD +20 -19
- {tkfluent-0.1.2.dist-info → tkfluent-0.1.4.dist-info}/WHEEL +0 -0
tkflu/label.py
CHANGED
@@ -41,17 +41,19 @@ class FluLabel(DDrawWidget, FluToolTipBase, FluGradient):
|
|
41
41
|
def _draw(self, event=None, tempcolor=None):
|
42
42
|
super()._draw(event)
|
43
43
|
|
44
|
-
self.delete("all")
|
45
|
-
|
46
44
|
if tempcolor:
|
47
45
|
_text_color = tempcolor
|
48
46
|
else:
|
49
47
|
_text_color = self.attributes.text_color
|
50
48
|
|
51
|
-
|
52
|
-
self.
|
53
|
-
|
54
|
-
|
49
|
+
if not hasattr(self, "element_text"):
|
50
|
+
self.element_text = self.create_text(
|
51
|
+
self.winfo_width() / 2, self.winfo_height() / 2, anchor="center",
|
52
|
+
fill=_text_color, text=self.attributes.text, font=self.attributes.font
|
53
|
+
)
|
54
|
+
else:
|
55
|
+
self.coords(self.element_text, self.winfo_width() / 2, self.winfo_height() / 2)
|
56
|
+
self.itemconfigure(self.element_text, fill=_text_color, text=self.attributes.text, font=self.attributes.font)
|
55
57
|
|
56
58
|
def theme(self, mode="light", animation_steps: int = None, animation_step_time: int = None):
|
57
59
|
from .designs.label import label
|
tkflu/menubar.py
CHANGED
@@ -141,24 +141,31 @@ class FluMenuBar(Frame, DObject, FluGradient):
|
|
141
141
|
m = menubar(mode)
|
142
142
|
self.mode = mode
|
143
143
|
if hasattr(self, "tk"):
|
144
|
-
if
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
144
|
+
if not animation_steps == 0 or not animation_step_time == 0:
|
145
|
+
if mode.lower() == "dark":
|
146
|
+
back_colors = self.generate_hex2hex(self.attributes.back_color, m["back_color"], steps=animation_steps)
|
147
|
+
for i in range(animation_steps):
|
148
|
+
def update(ii=i): # 使用默认参数立即捕获i的值
|
149
|
+
self.dconfigure(back_color=back_colors[ii])
|
150
|
+
self._draw()
|
151
|
+
|
152
|
+
self.after(i * animation_step_time, update) # 直接传递函数,不需要lambda
|
153
|
+
else:
|
154
|
+
back_colors = self.generate_hex2hex(self.attributes.back_color, m["back_color"], steps=animation_steps)
|
155
|
+
for i in range(animation_steps):
|
156
|
+
def update(ii=i): # 使用默认参数立即捕获i的值
|
157
|
+
self.dconfigure(back_color=back_colors[ii])
|
158
|
+
self._draw()
|
159
|
+
|
160
|
+
self.after(i * animation_step_time, update) # 直接传递函数,不需要lambda
|
161
|
+
|
162
|
+
self.after(animation_steps * animation_step_time + 50, lambda: self.update_children())
|
152
163
|
else:
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
self.after(i * animation_step_time, update) # 直接传递函数,不需要lambda
|
160
|
-
|
161
|
-
self.after(animation_steps * animation_step_time + 50, lambda: self.update_children())
|
164
|
+
if mode.lower() == "dark":
|
165
|
+
self.dconfigure(back_color=m["back_color"])
|
166
|
+
else:
|
167
|
+
self.dconfigure(back_color=m["back_color"])
|
168
|
+
self._draw()
|
162
169
|
|
163
170
|
def _draw(self, event=None):
|
164
171
|
self.config(background=self.attributes.back_color)
|
tkflu/popupwindow.py
CHANGED
@@ -7,7 +7,8 @@ class FluPopupWindow(Toplevel):
|
|
7
7
|
|
8
8
|
self.theme(mode=mode)
|
9
9
|
|
10
|
-
|
10
|
+
if width > 0 and height > 0:
|
11
|
+
self.geometry(f"{width}x{height}")
|
11
12
|
|
12
13
|
if custom:
|
13
14
|
self.transient_color = transparent_color
|
@@ -19,11 +20,43 @@ class FluPopupWindow(Toplevel):
|
|
19
20
|
self.bind("<FocusOut>", self._event_focusout, add="+")
|
20
21
|
|
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() # 启动动画"""
|
22
39
|
self.withdraw()
|
23
40
|
|
24
41
|
def popup(self, x, y):
|
25
42
|
self.geometry(f"+{x}+{y}")
|
26
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() # 启动动画
|
27
60
|
|
28
61
|
def theme(self, mode=None):
|
29
62
|
if mode:
|
tkflu/slider.py
CHANGED
@@ -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
|
9
|
+
def create_track(
|
10
10
|
self,
|
11
|
-
|
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
|
-
|
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(
|
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
|
-
(
|
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=
|
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
|
-
(
|
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=
|
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
|
-
|
66
|
-
|
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
|
-
(
|
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
|
-
(
|
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
|
-
(
|
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
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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.
|
205
|
-
|
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 =
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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.
|
247
|
-
|
248
|
-
|
249
|
-
|
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
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
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
|
|
tkflu/text.py
CHANGED
@@ -172,6 +172,8 @@ class FluText(FluTextCanvas, DDrawWidget, FluToolTipBase):
|
|
172
172
|
height=self.winfo_height() - _border_width * 2 - _radius
|
173
173
|
)
|
174
174
|
|
175
|
+
if hasattr(self, "element_border"):
|
176
|
+
self.delete(self.element_border)
|
175
177
|
self.element_border = self.create_round_rectangle(
|
176
178
|
0, 0, width, height, _radius, temppath=self.temppath,
|
177
179
|
fill=_back_color, fill_opacity=_back_opacity, stop1=_stop1, stop2=_stop2,
|
@@ -179,20 +181,50 @@ class FluText(FluTextCanvas, DDrawWidget, FluToolTipBase):
|
|
179
181
|
outline2_opacity=_border_color2_opacity,
|
180
182
|
width=_border_width
|
181
183
|
)
|
182
|
-
|
184
|
+
"""if _underline_fill:
|
185
|
+
if not hasattr(self, "element_line"):
|
186
|
+
self.element_line = self.create_line(
|
187
|
+
_radius / 3 + _border_width, self.winfo_height() - _radius / 3,
|
188
|
+
self.winfo_width() - _radius / 3 - _border_width * 2, self.winfo_height() - _radius / 3,
|
189
|
+
width=_underline_width, fill=_underline_fill
|
190
|
+
)
|
191
|
+
else:
|
192
|
+
self.coords(
|
193
|
+
self.element_line, _radius / 3 + _border_width, self.winfo_height() - _radius / 3,
|
194
|
+
self.winfo_width() - _radius / 3 - _border_width * 2, self.winfo_height() - _radius / 3,
|
195
|
+
)
|
196
|
+
self.itemconfigure(self.element_line, width=_underline_width, fill=_underline_fill)
|
197
|
+
"""
|
198
|
+
if hasattr(self, "element_line"):
|
199
|
+
self.delete(self.element_line)
|
183
200
|
if _underline_fill:
|
184
201
|
self.element_line = self.create_line(
|
185
202
|
_radius / 3 + _border_width, self.winfo_height() - _radius / 3,
|
186
203
|
self.winfo_width() - _radius / 3 - _border_width * 2, self.winfo_height() - _radius / 3,
|
187
204
|
width=_underline_width, fill=_underline_fill
|
188
205
|
)
|
189
|
-
|
206
|
+
"""
|
207
|
+
if not hasattr(self, "element_text"):
|
208
|
+
self.element_text = self.create_window(
|
209
|
+
self.winfo_width() / 2, self.winfo_height() / 2,
|
210
|
+
window=self.text,
|
211
|
+
width=self.winfo_width() - _border_width * 2 - _radius,
|
212
|
+
height=self.winfo_height() - _border_width * 2 - _radius
|
213
|
+
)
|
214
|
+
else:
|
215
|
+
self.coords(self.element_text, self.winfo_width() / 2, self.winfo_height() / 2,
|
216
|
+
self.winfo_width() - _border_width * 2 - _radius, self.winfo_height() - _border_width * 2 - _radius)
|
217
|
+
"""
|
218
|
+
if hasattr(self, "element_text"):
|
219
|
+
self.delete(self.element_text)
|
190
220
|
self.element_text = self.create_window(
|
191
221
|
self.winfo_width() / 2, self.winfo_height() / 2,
|
192
222
|
window=self.text,
|
193
223
|
width=self.winfo_width() - _border_width * 2 - _radius,
|
194
224
|
height=self.winfo_height() - _border_width * 2 - _radius
|
195
225
|
)
|
226
|
+
self.tag_raise(self.element_text, self.element_border)
|
227
|
+
self.tag_raise(self.element_line, self.element_border)
|
196
228
|
|
197
229
|
#self.tag_raise(self.element_text)
|
198
230
|
|
tkflu/thememanager.py
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
from .window import FluWindow
|
2
2
|
from .toplevel import FluToplevel
|
3
|
+
from typing import Union
|
3
4
|
|
4
5
|
|
5
6
|
class FluThemeManager(object):
|
6
|
-
def __init__(self, window=None, mode: str = "light", delay: int
|
7
|
+
def __init__(self, window=None, mode: str = "light", delay: Union[int, None] = 100):
|
7
8
|
if window:
|
8
9
|
self._window = window
|
9
10
|
else:
|
10
11
|
from tkinter import _default_root
|
11
12
|
self._window = _default_root
|
12
13
|
self._mode = mode
|
13
|
-
self.mode(self._mode)
|
14
|
-
self._window.after(delay, lambda: self.mode(self._mode))
|
14
|
+
#self.mode(self._mode)
|
15
|
+
#self._window.after(delay, lambda: self.mode(self._mode))
|
15
16
|
|
16
|
-
def mode(self, mode: str, delay: int
|
17
|
-
def
|
17
|
+
def mode(self, mode: str, delay: Union[int, None] = None):
|
18
|
+
def update_window():
|
18
19
|
self._mode = mode
|
19
20
|
if hasattr(self._window, "theme"):
|
20
21
|
self._window.theme(mode=mode)
|
21
22
|
if hasattr(self._window, "_draw"):
|
22
23
|
self._window._draw()
|
23
24
|
self._window.update()
|
25
|
+
def update_children():
|
24
26
|
for widget in self._window.winfo_children():
|
25
27
|
if hasattr(widget, "theme"):
|
26
28
|
widget.theme(mode=mode)
|
@@ -29,21 +31,20 @@ class FluThemeManager(object):
|
|
29
31
|
if hasattr(widget, "update_children"):
|
30
32
|
widget.update_children()
|
31
33
|
#widget.update()
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def __():
|
34
|
+
update_window()
|
35
|
+
update_children()
|
36
|
+
|
37
|
+
def update_children2():
|
37
38
|
for widget in self._window.winfo_children():
|
38
39
|
if hasattr(widget, "_draw"):
|
39
40
|
widget._draw()
|
40
41
|
if hasattr(widget, "update_children"):
|
41
42
|
widget.update_children()
|
42
43
|
widget.update()
|
43
|
-
#print(len(self._window.winfo_children()))
|
44
|
-
self._window.after(delay+len(self._window.winfo_children()), __)
|
45
44
|
|
46
|
-
|
45
|
+
#self._window.after(len(self._window.winfo_children())*50, update_children2)
|
46
|
+
|
47
|
+
def toggle(self, delay: Union[int, None] = None):
|
47
48
|
if self._mode == "light":
|
48
49
|
mode = "dark"
|
49
50
|
else:
|