tkfluent 0.0.6__py3-none-any.whl → 0.0.9__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 +4 -1
- tkflu/__main__.py +38 -3
- tkflu/badge.py +4 -1
- tkflu/button.py +9 -6
- tkflu/bwm.py +2 -0
- tkflu/constants.py +10 -0
- tkflu/defs.py +25 -0
- tkflu/demos/__init__.py +1 -0
- tkflu/demos/acrylic1.py +18 -0
- tkflu/demos/tooltip.py +13 -0
- tkflu/designs/slider.py +253 -0
- tkflu/designs/tooltip.py +15 -0
- tkflu/designs/window.py +2 -2
- tkflu/entry.py +7 -2
- tkflu/label.py +2 -1
- tkflu/menu.py +6 -5
- tkflu/popupwindow.py +6 -4
- tkflu/slider.py +404 -0
- tkflu/text.py +9 -2
- tkflu/thememanager.py +20 -15
- tkflu/togglebutton.py +4 -1
- tkflu/tooltip.py +146 -3
- tkflu/window.py +14 -10
- tkfluent-0.0.9.dist-info/METADATA +82 -0
- tkfluent-0.0.9.dist-info/RECORD +48 -0
- {tkfluent-0.0.6.dist-info → tkfluent-0.0.9.dist-info}/WHEEL +1 -1
- tkfluent-0.0.6.dist-info/METADATA +0 -26
- tkfluent-0.0.6.dist-info/RECORD +0 -42
tkflu/slider.py
ADDED
@@ -0,0 +1,404 @@
|
|
1
|
+
from tkdeft.windows.draw import DSvgDraw
|
2
|
+
from tkdeft.windows.canvas import DCanvas
|
3
|
+
from tkdeft.windows.drawwidget import DDrawWidget
|
4
|
+
|
5
|
+
from .designs.slider import slider
|
6
|
+
|
7
|
+
|
8
|
+
class FluSliderDraw(DSvgDraw):
|
9
|
+
def create_slider(
|
10
|
+
self,
|
11
|
+
x1, y1, x2, y2,
|
12
|
+
x3, # 滑块的x坐标
|
13
|
+
r1, # 滑块外圆半径
|
14
|
+
r2, # 滑块内圆半径
|
15
|
+
temppath=None,
|
16
|
+
fill="transparent", fill_opacity=1, # 滑块外圆的背景颜色、透明度
|
17
|
+
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, # 滑块进度条的选中部分矩形的背景颜色、高度、透明度
|
22
|
+
rail_fill="transparent", rail_opacity=1 #
|
23
|
+
):
|
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("")
|
40
|
+
|
41
|
+
drawing[1].add(
|
42
|
+
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坐标 - 滑块外半径 + 滑块内半径 | 矩形高度:进度条的高度
|
48
|
+
rx=radius,
|
49
|
+
fill=rail_fill, fill_opacity=rail_opacity
|
50
|
+
)
|
51
|
+
) # 滑块进度未选中区域 (占全部)
|
52
|
+
|
53
|
+
drawing[1].add(
|
54
|
+
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位置) | 矩形高度:进度条的高度
|
60
|
+
rx=radius,
|
61
|
+
fill=track_fill, fill_opacity=track_opacity, fill_rule="evenodd"
|
62
|
+
)
|
63
|
+
) # 滑块进度左边的选中区域 (只左部分)
|
64
|
+
|
65
|
+
x = x3
|
66
|
+
y = (y2 - y1) / 2
|
67
|
+
|
68
|
+
drawing[1].add(
|
69
|
+
drawing[1].circle(
|
70
|
+
(x, y), r1,
|
71
|
+
fill=stroke, fill_opacity=1, fill_rule="evenodd"
|
72
|
+
)
|
73
|
+
) # 圆形滑块的伪阴影边框
|
74
|
+
drawing[1].add(
|
75
|
+
drawing[1].circle(
|
76
|
+
(x, y), r1 - 1,
|
77
|
+
fill=fill, fill_opacity=fill_opacity, fill_rule="nonzero"
|
78
|
+
)
|
79
|
+
) # 圆形滑块的外填充
|
80
|
+
drawing[1].add(
|
81
|
+
drawing[1].circle(
|
82
|
+
(x, y), r2,
|
83
|
+
fill=inner_fill, fill_opacity=inner_fill_opacity, fill_rule="nonzero"
|
84
|
+
)
|
85
|
+
) # 圆形滑块的内填充
|
86
|
+
drawing[1].save()
|
87
|
+
return drawing[0]
|
88
|
+
|
89
|
+
|
90
|
+
class FluSliderCanvas(DCanvas):
|
91
|
+
draw = FluSliderDraw
|
92
|
+
|
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,
|
105
|
+
outline=outline, outline_opacity=outline_opacity,
|
106
|
+
outline2=outline2, outline2_opacity=outline2_opacity,
|
107
|
+
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
|
+
)
|
111
|
+
self._tkimg = self.svgdraw.create_tksvg_image(self._img)
|
112
|
+
return self.create_image(x1, y1, anchor="nw", image=self._tkimg)
|
113
|
+
|
114
|
+
|
115
|
+
class FluSlider(FluSliderCanvas, DDrawWidget):
|
116
|
+
def __init__(self, *args,
|
117
|
+
text="",
|
118
|
+
width=70,
|
119
|
+
height=28,
|
120
|
+
font=None,
|
121
|
+
mode="light",
|
122
|
+
state="normal",
|
123
|
+
value=20,
|
124
|
+
max=100,
|
125
|
+
min=0,
|
126
|
+
**kwargs
|
127
|
+
):
|
128
|
+
|
129
|
+
"""
|
130
|
+
|
131
|
+
初始化类
|
132
|
+
|
133
|
+
:param args: 参照tkinter.Canvas.__init__
|
134
|
+
:param text:
|
135
|
+
:param width:
|
136
|
+
:param height:
|
137
|
+
:param font:
|
138
|
+
:param mode: Fluent主题模式 分为 “light” “dark”
|
139
|
+
:param style:
|
140
|
+
:param kwargs: 参照tkinter.Canvas.__init__
|
141
|
+
"""
|
142
|
+
|
143
|
+
self._init(mode)
|
144
|
+
|
145
|
+
self.dconfigure(
|
146
|
+
state=state,
|
147
|
+
value=value,
|
148
|
+
max=max, min=min,
|
149
|
+
)
|
150
|
+
|
151
|
+
super().__init__(*args, width=width, height=height, **kwargs)
|
152
|
+
|
153
|
+
self.bind("<<Clicked>>", lambda event=None: self.focus_set(), add="+")
|
154
|
+
|
155
|
+
self.bind("<Motion>", self._event_button1_motion)
|
156
|
+
|
157
|
+
from .defs import set_default_font
|
158
|
+
set_default_font(font, self.attributes)
|
159
|
+
|
160
|
+
def _init(self, mode):
|
161
|
+
from easydict import EasyDict
|
162
|
+
|
163
|
+
self.attributes = EasyDict(
|
164
|
+
{
|
165
|
+
"command": None,
|
166
|
+
"state": None,
|
167
|
+
|
168
|
+
"value": 20,
|
169
|
+
"max": 100,
|
170
|
+
"min": 0,
|
171
|
+
|
172
|
+
"rest": {},
|
173
|
+
"hover": {},
|
174
|
+
"pressed": {},
|
175
|
+
"disabled": {},
|
176
|
+
}
|
177
|
+
)
|
178
|
+
|
179
|
+
self.theme(mode)
|
180
|
+
|
181
|
+
def _draw(self, event=None):
|
182
|
+
|
183
|
+
"""
|
184
|
+
重新绘制组件
|
185
|
+
|
186
|
+
:param event:
|
187
|
+
"""
|
188
|
+
|
189
|
+
super()._draw(event)
|
190
|
+
|
191
|
+
#print("width:", self.winfo_width(), "\n", "height:", self.winfo_height(), sep="")
|
192
|
+
|
193
|
+
#print("")
|
194
|
+
|
195
|
+
self.delete("all")
|
196
|
+
|
197
|
+
state = self.dcget("state")
|
198
|
+
|
199
|
+
_dict = None
|
200
|
+
|
201
|
+
if state == "normal":
|
202
|
+
if event:
|
203
|
+
if self.enter:
|
204
|
+
if self.button1:
|
205
|
+
_dict = self.attributes.pressed
|
206
|
+
else:
|
207
|
+
_dict = self.attributes.hover
|
208
|
+
else:
|
209
|
+
_dict = self.attributes.rest
|
210
|
+
else:
|
211
|
+
_dict = self.attributes.rest
|
212
|
+
else:
|
213
|
+
_dict = self.attributes.disabled
|
214
|
+
|
215
|
+
_radius = _dict.radius
|
216
|
+
|
217
|
+
_track_height = _dict.track.width
|
218
|
+
_track_back_color = _dict.track.back_color
|
219
|
+
_track_back_opacity = _dict.track.back_opacity
|
220
|
+
|
221
|
+
_rail_back_color = _dict.rail.back_color
|
222
|
+
_rail_back_opacity = _dict.rail.back_opacity
|
223
|
+
|
224
|
+
_thumb_radius = _dict.thumb.radius
|
225
|
+
_thumb_inner_radius = _dict.thumb.inner_radius
|
226
|
+
|
227
|
+
_thumb_back_color = _dict.thumb.back_color
|
228
|
+
_thumb_back_opacity = _dict.thumb.back_opacity
|
229
|
+
|
230
|
+
_thumb_border_color = _dict.thumb.border_color
|
231
|
+
_thumb_border_color_opacity = _dict.thumb.border_color_opacity
|
232
|
+
|
233
|
+
_thumb_border_color2 = _dict.thumb.border_color2
|
234
|
+
_thumb_border_color2_opacity = _dict.thumb.border_color2_opacity
|
235
|
+
|
236
|
+
_thumb_inner_back_color = _dict.thumb.inner_back_color
|
237
|
+
_thumb_inner_back_opacity = _dict.thumb.inner_back_opacity
|
238
|
+
|
239
|
+
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
|
245
|
+
|
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,
|
250
|
+
outline=_thumb_border_color, outline_opacity=_thumb_border_color_opacity,
|
251
|
+
outline2=_thumb_border_color2, outline2_opacity=_thumb_border_color2_opacity,
|
252
|
+
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
|
+
)
|
256
|
+
|
257
|
+
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("")
|
268
|
+
|
269
|
+
def _event_button1_motion(self, event):
|
270
|
+
self.pos(event)
|
271
|
+
|
272
|
+
def _event_on_button1(self, event=None):
|
273
|
+
super()._event_on_button1(event=event)
|
274
|
+
self.pos(event)
|
275
|
+
|
276
|
+
def theme(self, mode=None):
|
277
|
+
if mode:
|
278
|
+
self.mode = mode
|
279
|
+
if self.mode.lower() == "dark":
|
280
|
+
self._dark()
|
281
|
+
else:
|
282
|
+
self._light()
|
283
|
+
|
284
|
+
def _theme(self, mode):
|
285
|
+
r = slider(mode, "rest")
|
286
|
+
h = slider(mode, "hover")
|
287
|
+
p = slider(mode, "pressed")
|
288
|
+
d = slider(mode, "disabled")
|
289
|
+
self.dconfigure(
|
290
|
+
rest={
|
291
|
+
"radius": r["radius"],
|
292
|
+
"thumb": {
|
293
|
+
"radius": r["thumb"]["radius"],
|
294
|
+
"inner_radius": r["thumb"]["inner_radius"],
|
295
|
+
|
296
|
+
"back_color": r["thumb"]["back_color"],
|
297
|
+
"back_opacity": r["thumb"]["back_opacity"],
|
298
|
+
|
299
|
+
"border_color": r["thumb"]["border_color"],
|
300
|
+
"border_color_opacity": r["thumb"]["border_color_opacity"],
|
301
|
+
"border_color2": r["thumb"]["border_color2"],
|
302
|
+
"border_color2_opacity": r["thumb"]["border_color2_opacity"],
|
303
|
+
|
304
|
+
"inner_back_color": r["thumb"]["inner_back_color"],
|
305
|
+
"inner_back_opacity": r["thumb"]["inner_back_opacity"],
|
306
|
+
},
|
307
|
+
"track": {
|
308
|
+
"back_color": r["track"]["back_color"],
|
309
|
+
"back_opacity": r["track"]["back_opacity"],
|
310
|
+
"width": r["track"]["width"]
|
311
|
+
},
|
312
|
+
"rail": {
|
313
|
+
"back_color": r["rail"]["back_color"],
|
314
|
+
"back_opacity": r["rail"]["back_opacity"],
|
315
|
+
}
|
316
|
+
},
|
317
|
+
hover={
|
318
|
+
"radius": h["radius"],
|
319
|
+
"thumb": {
|
320
|
+
"radius": h["thumb"]["radius"],
|
321
|
+
"inner_radius": h["thumb"]["inner_radius"],
|
322
|
+
|
323
|
+
"back_color": h["thumb"]["back_color"],
|
324
|
+
"back_opacity": h["thumb"]["back_opacity"],
|
325
|
+
|
326
|
+
"border_color": h["thumb"]["border_color"],
|
327
|
+
"border_color_opacity": h["thumb"]["border_color_opacity"],
|
328
|
+
"border_color2": h["thumb"]["border_color2"],
|
329
|
+
"border_color2_opacity": h["thumb"]["border_color2_opacity"],
|
330
|
+
|
331
|
+
"inner_back_color": h["thumb"]["inner_back_color"],
|
332
|
+
"inner_back_opacity": h["thumb"]["inner_back_opacity"],
|
333
|
+
},
|
334
|
+
"track": {
|
335
|
+
"back_color": h["track"]["back_color"],
|
336
|
+
"back_opacity": h["track"]["back_opacity"],
|
337
|
+
"width": h["track"]["width"]
|
338
|
+
},
|
339
|
+
"rail": {
|
340
|
+
"back_color": h["rail"]["back_color"],
|
341
|
+
"back_opacity": h["rail"]["back_opacity"],
|
342
|
+
}
|
343
|
+
},
|
344
|
+
pressed={
|
345
|
+
"radius": p["radius"],
|
346
|
+
"thumb": {
|
347
|
+
"radius": p["thumb"]["radius"],
|
348
|
+
"inner_radius": p["thumb"]["inner_radius"],
|
349
|
+
|
350
|
+
"back_color": p["thumb"]["back_color"],
|
351
|
+
"back_opacity": p["thumb"]["back_opacity"],
|
352
|
+
|
353
|
+
"border_color": p["thumb"]["border_color"],
|
354
|
+
"border_color_opacity": p["thumb"]["border_color_opacity"],
|
355
|
+
"border_color2": p["thumb"]["border_color2"],
|
356
|
+
"border_color2_opacity": p["thumb"]["border_color2_opacity"],
|
357
|
+
|
358
|
+
"inner_back_color": p["thumb"]["inner_back_color"],
|
359
|
+
"inner_back_opacity": p["thumb"]["inner_back_opacity"],
|
360
|
+
},
|
361
|
+
"track": {
|
362
|
+
"back_color": p["track"]["back_color"],
|
363
|
+
"back_opacity": p["track"]["back_opacity"],
|
364
|
+
"width": p["track"]["width"]
|
365
|
+
},
|
366
|
+
"rail": {
|
367
|
+
"back_color": p["rail"]["back_color"],
|
368
|
+
"back_opacity": p["rail"]["back_opacity"],
|
369
|
+
}
|
370
|
+
},
|
371
|
+
disabled={
|
372
|
+
"radius": d["radius"],
|
373
|
+
"thumb": {
|
374
|
+
"radius": d["thumb"]["radius"],
|
375
|
+
"inner_radius": d["thumb"]["inner_radius"],
|
376
|
+
|
377
|
+
"back_color": d["thumb"]["back_color"],
|
378
|
+
"back_opacity": d["thumb"]["back_opacity"],
|
379
|
+
|
380
|
+
"border_color": d["thumb"]["border_color"],
|
381
|
+
"border_color_opacity": d["thumb"]["border_color_opacity"],
|
382
|
+
"border_color2": d["thumb"]["border_color2"],
|
383
|
+
"border_color2_opacity": d["thumb"]["border_color2_opacity"],
|
384
|
+
|
385
|
+
"inner_back_color": d["thumb"]["inner_back_color"],
|
386
|
+
"inner_back_opacity": d["thumb"]["inner_back_opacity"],
|
387
|
+
},
|
388
|
+
"track": {
|
389
|
+
"back_color": d["track"]["back_color"],
|
390
|
+
"back_opacity": d["track"]["back_opacity"],
|
391
|
+
"width": d["track"]["width"]
|
392
|
+
},
|
393
|
+
"rail": {
|
394
|
+
"back_color": d["rail"]["back_color"],
|
395
|
+
"back_opacity": d["rail"]["back_opacity"],
|
396
|
+
}
|
397
|
+
}
|
398
|
+
)
|
399
|
+
|
400
|
+
def _light(self):
|
401
|
+
self._theme("light")
|
402
|
+
|
403
|
+
def _dark(self):
|
404
|
+
self._theme("dark")
|
tkflu/text.py
CHANGED
@@ -72,7 +72,10 @@ class FluTextCanvas(DCanvas):
|
|
72
72
|
create_roundrect = create_round_rectangle
|
73
73
|
|
74
74
|
|
75
|
-
|
75
|
+
from .tooltip import FluToolTipBase
|
76
|
+
|
77
|
+
|
78
|
+
class FluText(FluTextCanvas, DDrawWidget, FluToolTipBase):
|
76
79
|
def __init__(self, *args,
|
77
80
|
width=120,
|
78
81
|
height=90,
|
@@ -96,7 +99,7 @@ class FluText(FluTextCanvas, DDrawWidget):
|
|
96
99
|
|
97
100
|
super().__init__(*args, width=width, height=height, cursor=cursor, **kwargs)
|
98
101
|
|
99
|
-
self.bind("<
|
102
|
+
self.bind("<Button-1>", lambda e: self.text.focus_set(), add="+")
|
100
103
|
|
101
104
|
self.dconfigure(
|
102
105
|
state=state,
|
@@ -191,9 +194,13 @@ class FluText(FluTextCanvas, DDrawWidget):
|
|
191
194
|
height=self.winfo_height() - _border_width * 2 - _radius
|
192
195
|
)
|
193
196
|
|
197
|
+
#self.tag_raise(self.element_text)
|
198
|
+
|
194
199
|
def _event_focus_in(self, event=None):
|
195
200
|
self.isfocus = True
|
196
201
|
|
202
|
+
self.text.focus_set()
|
203
|
+
|
197
204
|
self._draw(event)
|
198
205
|
|
199
206
|
def _event_focus_out(self, event=None):
|
tkflu/thememanager.py
CHANGED
@@ -3,7 +3,7 @@ from .toplevel import FluToplevel
|
|
3
3
|
|
4
4
|
|
5
5
|
class FluThemeManager(object):
|
6
|
-
def __init__(self, window=None, mode: str = "light"):
|
6
|
+
def __init__(self, window=None, mode: str = "light", delay: int or None = 100):
|
7
7
|
if window:
|
8
8
|
self._window = window
|
9
9
|
else:
|
@@ -11,18 +11,23 @@ class FluThemeManager(object):
|
|
11
11
|
self._window = _default_root
|
12
12
|
self._mode = mode
|
13
13
|
self.mode(self._mode)
|
14
|
-
self._window.after(
|
14
|
+
self._window.after(delay, lambda: self.mode(self._mode))
|
15
15
|
|
16
|
-
def mode(self, mode: str):
|
17
|
-
|
18
|
-
|
19
|
-
self._window
|
20
|
-
|
21
|
-
self._window
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
widget
|
26
|
-
|
27
|
-
widget
|
28
|
-
|
16
|
+
def mode(self, mode: str, delay: int or None = None):
|
17
|
+
def _():
|
18
|
+
self._mode = mode
|
19
|
+
if hasattr(self._window, "theme"):
|
20
|
+
self._window.theme(mode=mode)
|
21
|
+
if hasattr(self._window, "_draw"):
|
22
|
+
self._window._draw()
|
23
|
+
self._window.update()
|
24
|
+
for widget in self._window.winfo_children():
|
25
|
+
if hasattr(widget, "theme"):
|
26
|
+
widget.theme(mode=mode)
|
27
|
+
if hasattr(widget, "_draw"):
|
28
|
+
widget._draw()
|
29
|
+
widget.update()
|
30
|
+
if delay:
|
31
|
+
self._window.after(delay, _)
|
32
|
+
else:
|
33
|
+
_()
|
tkflu/togglebutton.py
CHANGED
@@ -59,7 +59,10 @@ class FluToggleButtonCanvas(DCanvas):
|
|
59
59
|
create_roundrect = create_round_rectangle_with_text
|
60
60
|
|
61
61
|
|
62
|
-
|
62
|
+
from .tooltip import FluToolTipBase
|
63
|
+
|
64
|
+
|
65
|
+
class FluToggleButton(FluToggleButtonCanvas, DDrawWidget, FluToolTipBase):
|
63
66
|
def __init__(self, *args,
|
64
67
|
text="",
|
65
68
|
width=120,
|
tkflu/tooltip.py
CHANGED
@@ -1,8 +1,151 @@
|
|
1
1
|
from .popupwindow import FluPopupWindow
|
2
|
+
from tkinter import Event, Widget
|
2
3
|
|
3
4
|
|
4
5
|
class FluToolTip(FluPopupWindow):
|
5
|
-
def __init__(self, widget, *args, **kwargs):
|
6
|
-
super().__init__(*args, **kwargs)
|
6
|
+
def __init__(self, widget: Widget, text, mode="light", delay=400, show_time=100.0, *args, **kwargs):
|
7
|
+
super().__init__(*args, transparent_color="#ebebeb", **kwargs)
|
8
|
+
|
9
|
+
from .label import FluLabel
|
10
|
+
from .frame import FluFrame
|
11
|
+
|
12
|
+
self.overrideredirect(True)
|
13
|
+
|
14
|
+
self._delay = delay
|
15
|
+
self._show_time = show_time
|
16
|
+
self._widget = widget
|
17
|
+
|
18
|
+
self._frame = FluFrame(self)
|
19
|
+
self._frame.theme(mode, style="popupmenu")
|
20
|
+
|
21
|
+
self._label = FluLabel(self._frame, text=text)
|
22
|
+
self._label.pack(fill="both", expand=True, padx=3, pady=3)
|
23
|
+
|
24
|
+
self._frame.pack(fill="both", expand=True, padx=3, pady=3)
|
25
|
+
|
26
|
+
self._widget.bind('<Enter>', self.enter, add="+")
|
27
|
+
self._widget.bind('<Leave>', self.leave, add="+")
|
28
|
+
|
29
|
+
#self.theme(mode)
|
30
|
+
|
31
|
+
def enter(self, event: Event):
|
32
|
+
def check() -> None:
|
33
|
+
if self._enter:
|
34
|
+
# 先定位工具提示位置
|
35
|
+
self.popup(
|
36
|
+
round(self._widget.winfo_rootx() + self._widget.winfo_width() / 2 - self.winfo_width() / 2),
|
37
|
+
round(self._widget.winfo_rooty() + self._widget.winfo_height() + 2)
|
38
|
+
)
|
39
|
+
self.wm_attributes("-alpha", 0.0)
|
40
|
+
self.deiconify()
|
41
|
+
|
42
|
+
# 设置初始透明度为0
|
43
|
+
|
44
|
+
|
45
|
+
# 渐显动画
|
46
|
+
def fade_in(step=0):
|
47
|
+
alpha = step / 10 # 分10步从0到1
|
48
|
+
self.wm_attributes("-alpha", alpha)
|
49
|
+
if step < 10:
|
50
|
+
self.after(int(round(self._show_time/10)), lambda: fade_in(step + 1)) # 每50ms增加一次透明度
|
51
|
+
|
52
|
+
fade_in() # 启动动画
|
53
|
+
|
54
|
+
self.id = self.after(self._delay, check)
|
55
|
+
self._enter = True
|
56
|
+
|
57
|
+
def leave(self, event):
|
58
|
+
self.after_cancel(self.id)
|
59
|
+
self._enter = False
|
60
|
+
self.withdraw()
|
61
|
+
|
62
|
+
def theme(self, mode=None):
|
63
|
+
from .designs.tooltip import tooltip
|
64
|
+
n = tooltip(mode)
|
65
|
+
self.configure(
|
66
|
+
background=n["back_color"]
|
67
|
+
)
|
68
|
+
self.wm_attributes("-transparentcolor", n["back_color"])
|
69
|
+
print(n["back_color"])
|
70
|
+
if hasattr(self, "_frame"):
|
71
|
+
self._frame.dconfigure(
|
72
|
+
back_color=n["frame_color"],
|
73
|
+
border_color=n["frame_border_color"],
|
74
|
+
border_color_opacity=1,
|
75
|
+
border_width=2,
|
76
|
+
radius=7,
|
77
|
+
)
|
78
|
+
if hasattr(self, "_label"):
|
79
|
+
self._label.theme(mode)
|
80
|
+
super().theme(mode)
|
81
|
+
|
82
|
+
|
83
|
+
class FluToolTip2(FluPopupWindow):
|
84
|
+
def __init__(self, widget, text, mode="light", *args, **kwargs):
|
85
|
+
super().__init__(*args, transparent_color="#ebebeb", **kwargs)
|
86
|
+
|
87
|
+
from .label import FluLabel
|
88
|
+
from .frame import FluFrame
|
89
|
+
|
90
|
+
self.overrideredirect(True)
|
91
|
+
|
92
|
+
self._widget = widget
|
93
|
+
|
94
|
+
self._frame = FluFrame(self)
|
95
|
+
self._frame.theme(mode, style="popupmenu")
|
96
|
+
|
97
|
+
self._label = FluLabel(self._frame, text=text)
|
98
|
+
self._label.pack(fill="both", expand=True, padx=3, pady=3)
|
99
|
+
|
100
|
+
self._frame.pack(fill="both", expand=True, padx=3, pady=3)
|
101
|
+
|
102
|
+
self._widget.bind('<Enter>', self.show, add="+")
|
103
|
+
self._widget.bind('<Leave>', self.hide, add="+")
|
104
|
+
self._widget.bind('<Motion>', self.move, add="+")
|
105
|
+
|
106
|
+
#self.theme(mode)
|
107
|
+
|
108
|
+
def show(self, event: Event):
|
109
|
+
self.popup(
|
110
|
+
round(event.x_root - self.winfo_width() / 2),
|
111
|
+
round(event.y_root + 10)
|
112
|
+
)
|
113
|
+
self.deiconify()
|
114
|
+
|
115
|
+
def hide(self, event):
|
116
|
+
self.withdraw()
|
117
|
+
|
118
|
+
def move(self, event):
|
119
|
+
self.popup(
|
120
|
+
round(event.x_root - self.winfo_width() / 2),
|
121
|
+
round(event.y_root + 10)
|
122
|
+
)
|
123
|
+
|
124
|
+
def theme(self, mode=None):
|
125
|
+
from .designs.tooltip import tooltip
|
126
|
+
n = tooltip(mode)
|
127
|
+
self.configure(
|
128
|
+
background=n["back_color"]
|
129
|
+
)
|
130
|
+
self.wm_attributes("-transparentcolor", n["back_color"])
|
131
|
+
print(n["back_color"])
|
132
|
+
if hasattr(self, "_frame"):
|
133
|
+
self._frame.dconfigure(
|
134
|
+
back_color=n["frame_color"],
|
135
|
+
border_color=n["frame_border_color"],
|
136
|
+
border_color_opacity=1,
|
137
|
+
border_width=2,
|
138
|
+
radius=7,
|
139
|
+
)
|
140
|
+
if hasattr(self, "_label"):
|
141
|
+
self._label.theme(mode)
|
142
|
+
super().theme(mode)
|
143
|
+
|
144
|
+
|
145
|
+
class FluToolTipBase:
|
146
|
+
def tooltip(self, *args, way=0, **kwargs):
|
147
|
+
if way == 0:
|
148
|
+
self._tooltip = FluToolTip(*args, widget=self, **kwargs)
|
149
|
+
elif way == 1:
|
150
|
+
self._tooltip = FluToolTip2(*args, widget=self, **kwargs)
|
7
151
|
|
8
|
-
self.widget = widget
|