tkfluent 0.0.1__tar.gz → 0.0.2__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.
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.1
2
+ Name: tkfluent
3
+ Version: 0.0.2
4
+ Summary: Fluent Design for Tkinter
5
+ Author: XiangQinxi
6
+ Author-email: xiangqinxi@outlook.com
7
+ Requires-Python: >=3.7,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.7
10
+ Classifier: Programming Language :: Python :: 3.8
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: easydict (>=1.13,<2.0)
16
+ Requires-Dist: pillow (>=10.2.0,<11.0.0)
17
+ Requires-Dist: svgwrite (>=1.4.3,<2.0.0)
18
+ Requires-Dist: tkdeft (>=0.0.7,<0.0.8)
19
+ Requires-Dist: tkextrafont (>=0.6.3,<0.7.0)
20
+ Requires-Dist: tksvg (>=0.7.4,<0.8.0)
21
+ Project-URL: Documentation, https://tkfluent.netlify.app
22
+ Description-Content-Type: text/markdown
23
+
24
+ # tkfluent
@@ -0,0 +1 @@
1
+ # tkfluent
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "tkfluent"
3
- version = "0.0.1"
3
+ version = "0.0.2"
4
4
  description = "Fluent Design for Tkinter"
5
5
  authors = ["XiangQinxi <xiangqinxi@outlook.com>"]
6
6
  readme = "README.md"
@@ -10,7 +10,13 @@ packages = [
10
10
  ]
11
11
 
12
12
  [tool.poetry.dependencies]
13
+ python = "^3.7"
14
+ tksvg = "^0.7.4"
15
+ tkextrafont = "^0.6.3"
16
+ svgwrite = "^1.4.3"
17
+ pillow = "^10.2.0"
13
18
  tkdeft = "^0.0.7"
19
+ easydict = "^1.13"
14
20
 
15
21
  [build-system]
16
22
  requires = ["poetry-core"]
@@ -12,7 +12,12 @@ from .button import FluButton
12
12
  from .entry import FluEntry
13
13
  from .frame import FluFrame
14
14
  from .label import FluLabel
15
+ from .menubar import FluMenuBar
16
+ from .popupmenu import FluPopupMenu
15
17
  from .text import FluText
18
+ from .thememanager import FluThemeManager
19
+ from .togglebutton import FluToggleButton
20
+ from .toplevel import FluToplevel
16
21
  from .window import FluWindow
17
22
 
18
23
  FluChip = FluBadge
@@ -20,5 +25,7 @@ FluPushButton = FluButton
20
25
  FluTextInput = FluEntry
21
26
  FluTextBox = FluText
22
27
  FluPanel = FluFrame
28
+ FluMainWindow = FluWindow
29
+ FluSubWindow = FluToplevel
23
30
 
24
31
  # 
@@ -0,0 +1,57 @@
1
+ from tkflu import *
2
+ from tkinter import *
3
+ from tkinter.font import *
4
+
5
+ root = FluWindow()
6
+ #root.wincustom(way=0)
7
+ root.wm_geometry("220x400")
8
+
9
+ popupmenu = FluPopupMenu()
10
+
11
+ thememanager = FluThemeManager()
12
+
13
+ menubar = FluMenuBar(root)
14
+ menubar.add_command(
15
+ label="FluMenu1", width=80, command=lambda: print("FluMenu -> Clicked")
16
+ )
17
+ menubar.pack(fill="x",)
18
+
19
+ frame = FluFrame(root)
20
+
21
+ badge1 = FluBadge(frame, text="FluBadge", width=60)
22
+ badge1.pack(padx=5, pady=5)
23
+
24
+ badge2 = FluBadge(frame, text="FluBadge (Accent)", width=120, style="accent")
25
+ badge2.pack(padx=5, pady=5)
26
+
27
+ button1 = FluButton(
28
+ frame, text="FluButton", command=lambda: print("FluButton -> Clicked")
29
+ )
30
+ button1.pack(fill="x", padx=5, pady=5)
31
+
32
+ button2 = FluButton(
33
+ frame, text="FluButton (Accent)", command=lambda: print("FluButton (Accent) -> Clicked"), style="accent"
34
+ )
35
+ button2.pack(fill="x", padx=5, pady=5)
36
+
37
+ def toggle1():
38
+ print(f"FluToggleButton -> Toggled -> Checked: {togglebutton1.dcget('checked')}")
39
+ if togglebutton1.dcget('checked'):
40
+ thememanager.mode("dark")
41
+ else:
42
+ thememanager.mode("light")
43
+
44
+ togglebutton1 = FluToggleButton(
45
+ frame, text="FluToggleButton", command=toggle1
46
+ )
47
+ togglebutton1.pack(fill="x", padx=5, pady=5)
48
+
49
+ entry1 = FluEntry(frame)
50
+ entry1.pack(fill="x", padx=5, pady=5)
51
+
52
+ text1 = FluText(frame)
53
+ text1.pack(fill="x", padx=5, pady=5)
54
+
55
+ frame.pack(fill="both", expand="yes", side="right", padx=5, pady=5)
56
+
57
+ root.mainloop()
@@ -47,6 +47,21 @@ class FluBadge(FluBadgeCanvas, DDrawWidget):
47
47
  mode="light",
48
48
  style="standard",
49
49
  **kwargs):
50
+
51
+ """
52
+
53
+ 初始化类
54
+
55
+ :param args: 参照tkinter.Canvas.__init__
56
+ :param text:
57
+ :param width:
58
+ :param height:
59
+ :param font:
60
+ :param mode: Fluent主题模式 分为 “light” “dark”
61
+ :param style:
62
+ :param kwargs: 参照tkinter.Canvas.__init__
63
+ """
64
+
50
65
  self._init(mode, style)
51
66
 
52
67
  super().__init__(*args, width=width, height=height, **kwargs)
@@ -80,6 +95,13 @@ class FluBadge(FluBadgeCanvas, DDrawWidget):
80
95
  self.theme(mode, style)
81
96
 
82
97
  def _draw(self, event=None):
98
+
99
+ """
100
+ 重新绘制组件
101
+
102
+ :param event:
103
+ """
104
+
83
105
  super()._draw(event)
84
106
 
85
107
  self.delete("all")
@@ -99,21 +121,25 @@ class FluBadge(FluBadgeCanvas, DDrawWidget):
99
121
  fill=_text_color, text=self.attributes.text, font=self.attributes.font
100
122
  )
101
123
 
102
- def theme(self, mode, style):
103
- if mode.lower() == "dark":
104
- if style.lower() == "accent":
124
+ def theme(self, mode=None, style=None):
125
+ if mode:
126
+ self.mode = mode
127
+ if style:
128
+ self.style = style
129
+ if self.mode.lower() == "dark":
130
+ if self.style.lower() == "accent":
105
131
  self._dark_accent()
106
132
  else:
107
133
  self._dark()
108
134
  else:
109
- if style.lower() == "accent":
135
+ if self.style.lower() == "accent":
110
136
  self._light_accent()
111
137
  else:
112
138
  self._light()
113
139
 
114
140
  def _light(self):
115
141
  self.dconfigure(
116
- back_color="#f0f0f0",
142
+ back_color="#f9f9f9",
117
143
  border_color="#f0f0f0",
118
144
  border_width=1,
119
145
  text_color="#191919",
@@ -0,0 +1,347 @@
1
+ from tkdeft.windows.draw import DSvgDraw
2
+ from tkdeft.windows.canvas import DCanvas
3
+ from tkdeft.windows.drawwidget import DDrawWidget
4
+
5
+
6
+ class FluButtonDraw(DSvgDraw):
7
+ def create_roundrect(self,
8
+ x1, y1, x2, y2, radius, radiusy=None, temppath=None,
9
+ fill="transparent", outline="black", outline2="black", width=1
10
+ ):
11
+ if radiusy:
12
+ _rx = radius
13
+ _ry = radiusy
14
+ else:
15
+ _rx, _ry = radius, radius
16
+ drawing = self.create_drawing(x2 - x1, y2 - y1, temppath=temppath)
17
+ border = drawing[1].linearGradient(start=(x1, y1), end=(x1, y2), id="DButton.Border")
18
+ border.add_stop_color("0%", outline)
19
+ border.add_stop_color("100%", outline2)
20
+ drawing[1].defs.add(border)
21
+ drawing[1].add(
22
+ drawing[1].rect(
23
+ (x1, y1), (x2 - x1, y2 - y1), _rx, _ry,
24
+ fill=fill, stroke_width=width,
25
+ stroke=f"url(#{border.get_id()})",
26
+ )
27
+ )
28
+ drawing[1].save()
29
+ return drawing[0]
30
+
31
+
32
+ class FluButtonCanvas(DCanvas):
33
+ draw = FluButtonDraw
34
+
35
+ def create_round_rectangle(self,
36
+ x1, y1, x2, y2, r1, r2=None, temppath=None,
37
+ fill="transparent", outline="black", outline2="black", width=1
38
+ ):
39
+ self._img = self.svgdraw.create_roundrect(
40
+ x1, y1, x2, y2, r1, r2, temppath=temppath,
41
+ fill=fill, outline=outline, outline2=outline2, width=width
42
+ )
43
+ self._tkimg = self.svgdraw.create_tksvg_image(self._img)
44
+ return self.create_image(x1, y1, anchor="nw", image=self._tkimg)
45
+
46
+ create_roundrect = create_round_rectangle
47
+
48
+
49
+ class FluButton(FluButtonCanvas, DDrawWidget):
50
+ def __init__(self, *args,
51
+ text="",
52
+ width=120,
53
+ height=32,
54
+ command=None,
55
+ font=None,
56
+ mode="light",
57
+ style="standard",
58
+ **kwargs):
59
+ self._init(mode, style)
60
+
61
+ super().__init__(*args, width=width, height=height, **kwargs)
62
+
63
+ if command is None:
64
+ def empty(): pass
65
+
66
+ command = empty
67
+
68
+ self.dconfigure(
69
+ text=text,
70
+ command=command
71
+ )
72
+
73
+ self.bind("<<Clicked>>", lambda event=None: self.focus_set(), add="+")
74
+ self.bind("<<Clicked>>", lambda event=None: self.attributes.command(), add="+")
75
+
76
+ self.bind("<Return>", lambda event=None: self.attributes.command(), add="+") # 可以使用回车键模拟点击
77
+
78
+ if font is None:
79
+ from tkdeft.utility.fonts import SegoeFont
80
+ self.attributes.font = SegoeFont()
81
+
82
+ def _init(self, mode, style):
83
+
84
+ from easydict import EasyDict
85
+
86
+ self.attributes = EasyDict(
87
+ {
88
+ "text": "",
89
+ "command": None,
90
+ "font": None,
91
+
92
+ "rest": {
93
+ "back_color": "#ffffff",
94
+ "border_color": "#f0f0f0",
95
+ "border_color2": "#d6d6d6",
96
+ "border_width": 1,
97
+ "radius": 6,
98
+ "text_color": "#1b1b1b",
99
+ },
100
+ "hover": {
101
+ "back_color": "#fcfcfc",
102
+ "border_color": "#f0f0f0",
103
+ "border_color2": "#d6d6d6",
104
+ "border_width": 1,
105
+ "radius": 6,
106
+ "text_color": "#1b1b1b",
107
+ },
108
+ "pressed": {
109
+ "back_color": "#fdfdfd",
110
+ "border_color": "#f0f0f0",
111
+ "border_color2": "#f0f0f0",
112
+ "border_width": 1,
113
+ "radius": 6,
114
+ "text_color": "#636363",
115
+ }
116
+ }
117
+ )
118
+
119
+ self.theme(mode=mode, style=style)
120
+
121
+ def _draw(self, event=None):
122
+ super()._draw(event)
123
+
124
+ self.delete("all")
125
+
126
+ if self.enter:
127
+ if self.button1:
128
+ _back_color = self.attributes.pressed.back_color
129
+ _border_color = self.attributes.pressed.border_color
130
+ _border_color2 = self.attributes.pressed.border_color2
131
+ _border_width = self.attributes.pressed.border_width
132
+ _radius = self.attributes.pressed.radius
133
+ _text_color = self.attributes.pressed.text_color
134
+ else:
135
+ _back_color = self.attributes.hover.back_color
136
+ _border_color = self.attributes.hover.border_color
137
+ _border_color2 = self.attributes.hover.border_color2
138
+ _border_width = self.attributes.hover.border_width
139
+ _radius = self.attributes.hover.radius
140
+ _text_color = self.attributes.hover.text_color
141
+ else:
142
+ _back_color = self.attributes.rest.back_color
143
+ _border_color = self.attributes.rest.border_color
144
+ _border_color2 = self.attributes.rest.border_color2
145
+ _border_width = self.attributes.rest.border_width
146
+ _radius = self.attributes.rest.radius
147
+ _text_color = self.attributes.rest.text_color
148
+
149
+ self.element_border = self.create_round_rectangle(
150
+ 0, 0, self.winfo_width(), self.winfo_height(), _radius, temppath=self.temppath,
151
+ fill=_back_color, outline=_border_color, outline2=_border_color2, width=_border_width
152
+ )
153
+ self.element_text = self.create_text(
154
+ self.winfo_width() / 2, self.winfo_height() / 2, anchor="center",
155
+ fill=_text_color, text=self.attributes.text, font=self.attributes.font
156
+ )
157
+
158
+ def theme(self, mode=None, style=None):
159
+ if mode:
160
+ self.mode = mode
161
+ if style:
162
+ self.style = style
163
+ if self.mode.lower() == "dark":
164
+ if self.style.lower() == "accent":
165
+ self._dark_accent()
166
+ elif self.style.lower() == "menu":
167
+ self._dark_menu()
168
+ else:
169
+ self._dark()
170
+ else:
171
+ if self.style.lower() == "accent":
172
+ self._light_accent()
173
+ elif self.style.lower() == "menu":
174
+ self._light_menu()
175
+ else:
176
+ self._light()
177
+
178
+ def _light(self):
179
+ self.dconfigure(
180
+ rest={
181
+ "back_color": "#ffffff",
182
+ "border_color": "#f0f0f0",
183
+ "border_color2": "#d6d6d6",
184
+ "border_width": 1,
185
+ "radius": 6,
186
+ "text_color": "#1b1b1b",
187
+ },
188
+ hover={
189
+ "back_color": "#fcfcfc",
190
+ "border_color": "#f0f0f0",
191
+ "border_color2": "#d6d6d6",
192
+ "border_width": 1,
193
+ "radius": 6,
194
+ "text_color": "#1b1b1b",
195
+ },
196
+ pressed={
197
+ "back_color": "#fdfdfd",
198
+ "border_color": "#f0f0f0",
199
+ "border_color2": "#f0f0f0",
200
+ "border_width": 1,
201
+ "radius": 6,
202
+ "text_color": "#636363",
203
+ }
204
+ )
205
+
206
+ def _light_menu(self):
207
+ self.dconfigure(
208
+ rest={
209
+ "back_color": "#ffffff",
210
+ "border_color": "white",
211
+ "border_color2": "white",
212
+ "border_width": 0,
213
+ "radius": 6,
214
+ "text_color": "#1b1b1b",
215
+ },
216
+ hover={
217
+ "back_color": "#eaeaea",
218
+ "border_color": "#f0f0f0",
219
+ "border_color2": "#d6d6d6",
220
+ "border_width": 0,
221
+ "radius": 6,
222
+ "text_color": "#1b1b1b",
223
+ },
224
+ pressed={
225
+ "back_color": "#ededed",
226
+ "border_color": "#f0f0f0",
227
+ "border_color2": "#f0f0f0",
228
+ "border_width": 0,
229
+ "radius": 6,
230
+ "text_color": "#636363",
231
+ }
232
+ )
233
+
234
+ def _light_accent(self):
235
+ self.dconfigure(
236
+ rest={
237
+ "back_color": "#005fb8",
238
+ "border_color": "#146cbe",
239
+ "border_color2": "#00396e",
240
+ "border_width": 1,
241
+ "radius": 6,
242
+ "text_color": "#ffffff",
243
+ },
244
+ hover={
245
+ "back_color": "#0359a9",
246
+ "border_color": "#1766b0",
247
+ "border_color2": "#0f4373",
248
+ "border_width": 1,
249
+ "radius": 6,
250
+ "text_color": "#ffffff",
251
+ },
252
+ pressed={
253
+ "back_color": "#005fb8",
254
+ "border_color": "#4389ca",
255
+ "border_color2": "#4389ca",
256
+ "border_width": 1,
257
+ "radius": 6,
258
+ "text_color": "#b4cbe0",
259
+ }
260
+ )
261
+
262
+ def _dark(self):
263
+ self.dconfigure(
264
+ rest={
265
+ "back_color": "#272727",
266
+ "border_color": "#303030",
267
+ "border_color2": "#262626",
268
+ "border_width": 1,
269
+ "radius": 6,
270
+ "text_color": "#ffffff",
271
+ },
272
+ hover={
273
+ "back_color": "#2d2d2d",
274
+ "border_color": "#303030",
275
+ "border_color2": "#262626",
276
+ "border_width": 1,
277
+ "radius": 6,
278
+ "text_color": "#ffffff",
279
+ },
280
+ pressed={
281
+ "back_color": "#212121",
282
+ "border_color": "#2a2a2a",
283
+ "border_color2": "#262626",
284
+ "border_width": 1,
285
+ "radius": 6,
286
+ "text_color": "#cfcfcf",
287
+ }
288
+ )
289
+
290
+ def _dark_menu(self):
291
+ self.dconfigure(
292
+ rest={
293
+ "back_color": "#202020",
294
+ "border_color": "black",
295
+ "border_color2": "black",
296
+ "border_width": 0,
297
+ "radius": 6,
298
+ "text_color": "#ffffff",
299
+ },
300
+ hover={
301
+ "back_color": "#2d2d2d",
302
+ "border_color": "#303030",
303
+ "border_color2": "#262626",
304
+ "border_width": 0,
305
+ "radius": 6,
306
+ "text_color": "#ffffff",
307
+ },
308
+ pressed={
309
+ "back_color": "#292929",
310
+ "border_color": "#2a2a2a",
311
+ "border_color2": "#262626",
312
+ "border_width": 0,
313
+ "radius": 6,
314
+ "text_color": "#cfcfcf",
315
+ }
316
+ )
317
+
318
+ def _dark_accent(self):
319
+ self.dconfigure(
320
+ rest={
321
+ "back_color": "#60cdff",
322
+ "border_color": "#6cd1ff",
323
+ "border_color2": "#56b4df",
324
+ "border_width": 1,
325
+ "radius": 6,
326
+ "text_color": "#000000",
327
+ },
328
+ hover={
329
+ "back_color": "#5abce9",
330
+ "border_color": "#67c1eb",
331
+ "border_color2": "#50a5cc",
332
+ "border_width": 1,
333
+ "radius": 6,
334
+ "text_color": "#000000",
335
+ },
336
+ pressed={
337
+ "back_color": "#52a9d1",
338
+ "border_color": "#60b0d5",
339
+ "border_color2": "#60b0d5",
340
+ "border_width": 1,
341
+ "radius": 6,
342
+ "text_color": "#295468",
343
+ }
344
+ )
345
+
346
+ def invoke(self):
347
+ self.attributes.command()