tkfluent 0.0.2__py3-none-any.whl → 0.0.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/menubar.py ADDED
@@ -0,0 +1,140 @@
1
+ from tkinter import Frame, Menu
2
+ from tkdeft.object import DObject
3
+
4
+
5
+ class FluMenuBar(Frame, DObject):
6
+ def __init__(self, *args, mode="light", height=40, **kwargs):
7
+ self._init(mode)
8
+
9
+ super().__init__(*args, height=height, **kwargs)
10
+
11
+ self._draw(None)
12
+
13
+ self.bind("<Configure>", self._event_configure, add="+")
14
+
15
+ def _init(self, mode):
16
+
17
+ from easydict import EasyDict
18
+
19
+ self.attributes = EasyDict(
20
+ {
21
+ "back_color": "#f3f3f3",
22
+
23
+ "actions": {}
24
+ }
25
+ )
26
+
27
+ self.theme(mode=mode)
28
+
29
+ def add_command(self, custom_widget=None, width=40, **kwargs):
30
+ if custom_widget:
31
+ widget = custom_widget(self)
32
+ else:
33
+ from .button import FluButton
34
+ widget = FluButton(self, width=width)
35
+ if "label" in kwargs:
36
+ label = kwargs.pop("label")
37
+ else:
38
+ label = ""
39
+ if "style" in kwargs:
40
+ style = kwargs.pop("style")
41
+ else:
42
+ style = "menu"
43
+ if "command" in kwargs:
44
+ command = kwargs.pop("command")
45
+ else:
46
+ def empty():
47
+ pass
48
+
49
+ command = empty
50
+ if "id" in kwargs:
51
+ id = kwargs.pop("id")
52
+ else:
53
+ id = widget._w
54
+ if hasattr(widget, "dconfigure"):
55
+ widget.dconfigure(text=label, command=command)
56
+ else:
57
+ if hasattr(widget, "configure"):
58
+ widget.configure(text=label, command=command)
59
+ if hasattr(widget, "theme"):
60
+ widget.theme(style=style)
61
+
62
+ widget.pack(side="left", padx=5, pady=5)
63
+ self.dcget("actions")[id] = widget
64
+
65
+ from .menu import FluMenu
66
+
67
+ def add_cascade(self, custom_widget=None, width=40, menu: FluMenu = None, **kwargs):
68
+ if custom_widget:
69
+ widget = custom_widget(self)
70
+ else:
71
+ from .button import FluButton
72
+ widget = FluButton(self, width=width)
73
+ if "label" in kwargs:
74
+ label = kwargs.pop("label")
75
+ else:
76
+ label = ""
77
+ if "style" in kwargs:
78
+ style = kwargs.pop("style")
79
+ else:
80
+ style = "menu"
81
+ if "id" in kwargs:
82
+ id = kwargs.pop("id")
83
+ else:
84
+ id = widget._w
85
+
86
+ def command():
87
+ menu.focus_set()
88
+ menu.popup(widget.winfo_rootx(), widget.winfo_rooty() + widget.winfo_height())
89
+ menu.window.deiconify()
90
+ menu.window.attributes("-topmost")
91
+
92
+ if hasattr(widget, "dconfigure"):
93
+ widget.dconfigure(text=label, command=command)
94
+ else:
95
+ if hasattr(widget, "configure"):
96
+ widget.configure(text=label, command=command)
97
+ if hasattr(widget, "theme"):
98
+ widget.theme(style=style)
99
+
100
+ widget.pack(side="left", padx=5, pady=5)
101
+ self.dcget("actions")[id] = widget
102
+
103
+ def action(self, id):
104
+ return self.dcget("actions")[id]
105
+
106
+ def theme(self, mode="light"):
107
+ self.theme_myself(mode=mode)
108
+
109
+ actions = self.dcget("actions")
110
+
111
+ for key in actions:
112
+ widget = actions[key]
113
+ if hasattr(widget, "theme"):
114
+ widget.theme(mode=mode)
115
+ if hasattr(widget, "_draw"):
116
+ widget._draw()
117
+ widget.update()
118
+
119
+ def theme_myself(self, mode="light"):
120
+ self.mode = mode
121
+ if mode.lower() == "dark":
122
+ self._dark()
123
+ else:
124
+ self._light()
125
+
126
+ def _light(self):
127
+ self.dconfigure(
128
+ back_color="#f3f3f3"
129
+ )
130
+
131
+ def _dark(self):
132
+ self.dconfigure(
133
+ back_color="#202020"
134
+ )
135
+
136
+ def _draw(self, event=None):
137
+ self.config(background=self.attributes.back_color)
138
+
139
+ def _event_configure(self, event=None):
140
+ self._draw(event)
tkflu/popupmenu.py ADDED
@@ -0,0 +1,56 @@
1
+ from .frame import FluFrame
2
+ from .popupwindow import FluPopupWindow
3
+
4
+
5
+ class FluPopupMenuWindow(FluPopupWindow):
6
+ def __init__(self, *args, **kwargs):
7
+ super().__init__(*args, **kwargs)
8
+
9
+
10
+ class FluPopupMenu(FluFrame):
11
+ def __init__(self, *args, width=100, height=46, transparent_color="#ffefa2", style="popupmenu", **kwargs):
12
+ self.window = FluPopupMenuWindow(transparent_color=transparent_color, width=width, height=height)
13
+
14
+ super().__init__(self.window, *args, style=style, **kwargs)
15
+
16
+ self.pack(fill="both", expand="yes", padx=5, pady=5)
17
+
18
+ def wm_attributes(self, *args, **kwargs):
19
+ self.window.wm_attributes(*args, **kwargs)
20
+
21
+ attributes = wm_attributes
22
+
23
+ def wm_protocol(self, *args, **kwargs):
24
+ self.window.wm_protocol(*args, **kwargs)
25
+
26
+ protocol = wm_protocol
27
+
28
+ def wm_deiconify(self, *args, **kwargs):
29
+ self.window.wm_deiconify(*args, **kwargs)
30
+
31
+ deiconify = wm_deiconify
32
+
33
+ def wm_withdraw(self, *args, **kwargs):
34
+ self.window.wm_withdraw(*args, **kwargs)
35
+
36
+ withdraw = wm_withdraw
37
+
38
+ def wm_iconify(self, *args, **kwargs):
39
+ self.window.wm_iconify(*args, **kwargs)
40
+
41
+ iconify = wm_iconify
42
+
43
+ def wm_resizable(self, *args, **kwargs):
44
+ self.window.wm_resizable(*args, **kwargs)
45
+
46
+ resizable = wm_resizable
47
+
48
+ def wm_geometry(self, *args, **kwargs):
49
+ self.window.wm_geometry(*args, **kwargs)
50
+
51
+ geometry = wm_geometry
52
+
53
+ def wm_popup(self, x, y):
54
+ self.window.popup(x=x, y=y)
55
+
56
+ popup = wm_popup
tkflu/popupwindow.py ADDED
@@ -0,0 +1,31 @@
1
+ from tkinter import Toplevel
2
+
3
+
4
+ class FluPopupWindow(Toplevel):
5
+ def __init__(self, *args, transparent_color="#ffefa2", mode="light", width=100, height=46, **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
+ self.transient_color = transparent_color
13
+ self.overrideredirect(True)
14
+ self.attributes("-transparentcolor", transparent_color)
15
+
16
+ self.withdraw()
17
+
18
+ self.bind("<FocusOut>", self._event_focusout, add="+")
19
+
20
+ def _event_focusout(self, event=None):
21
+ self.withdraw()
22
+
23
+ def popup(self, x, y):
24
+ self.geometry(f"+{x}+{y}")
25
+
26
+ def theme(self, mode=None):
27
+ if mode:
28
+ self.mode = mode
29
+ for widget in self.winfo_children():
30
+ if hasattr(widget, "theme"):
31
+ widget.theme(mode=self.mode.lower())
tkflu/text.py CHANGED
@@ -16,7 +16,7 @@ class FluTextDraw(DSvgDraw):
16
16
  drawing = self.create_drawing(x2 - x1, y2 - y1, temppath=temppath)
17
17
  border = drawing[1].linearGradient(start=(x1, y1), end=(x1, y2), id="DButton.Border")
18
18
  border.add_stop_color("0%", outline)
19
- border.add_stop_color("85%", outline)
19
+ border.add_stop_color("90%", outline)
20
20
  border.add_stop_color("100%", outline2)
21
21
  drawing[1].defs.add(border)
22
22
  drawing[1].add(
@@ -54,6 +54,7 @@ class FluText(FluTextCanvas, DDrawWidget):
54
54
  font=None,
55
55
  cursor="xterm",
56
56
  mode="light",
57
+ state="normal",
57
58
  **kwargs):
58
59
  self._init(mode)
59
60
 
@@ -70,6 +71,12 @@ class FluText(FluTextCanvas, DDrawWidget):
70
71
 
71
72
  super().__init__(*args, width=width, height=height, cursor=cursor, **kwargs)
72
73
 
74
+ self.bind("<FocusIn>", self._event_focus_in, add="+")
75
+
76
+ self.dconfigure(
77
+ state=state,
78
+ )
79
+
73
80
  if font is None:
74
81
  from tkdeft.utility.fonts import SegoeFont
75
82
  self.attributes.font = SegoeFont()
@@ -80,11 +87,11 @@ class FluText(FluTextCanvas, DDrawWidget):
80
87
  self.attributes = EasyDict(
81
88
  {
82
89
  "font": None,
90
+ "state": "normal",
83
91
 
84
92
  "rest": {},
85
-
86
- "focus": {}
87
-
93
+ "focus": {},
94
+ "disabled": {},
88
95
  }
89
96
  )
90
97
 
@@ -97,20 +104,32 @@ class FluText(FluTextCanvas, DDrawWidget):
97
104
 
98
105
  self.delete("all")
99
106
 
100
- if self.isfocus:
101
- _back_color = self.attributes.focus.back_color
102
- _border_color = self.attributes.focus.border_color
103
- _border_color2 = self.attributes.focus.border_color2
104
- _border_width = self.attributes.focus.border_width
105
- _radius = self.attributes.focus.radius
106
- _text_color = self.attributes.focus.text_color
107
+ state = self.dcget("state")
108
+
109
+ if state == "normal":
110
+ self.text.configure(state="normal")
111
+ if self.isfocus:
112
+ _back_color = self.attributes.focus.back_color
113
+ _border_color = self.attributes.focus.border_color
114
+ _border_color2 = self.attributes.focus.border_color2
115
+ _border_width = self.attributes.focus.border_width
116
+ _radius = self.attributes.focus.radius
117
+ _text_color = self.attributes.focus.text_color
118
+ else:
119
+ _back_color = self.attributes.rest.back_color
120
+ _border_color = self.attributes.rest.border_color
121
+ _border_color2 = self.attributes.rest.border_color2
122
+ _border_width = self.attributes.rest.border_width
123
+ _radius = self.attributes.rest.radius
124
+ _text_color = self.attributes.rest.text_color
107
125
  else:
108
- _back_color = self.attributes.rest.back_color
109
- _border_color = self.attributes.rest.border_color
110
- _border_color2 = self.attributes.rest.border_color2
111
- _border_width = self.attributes.rest.border_width
112
- _radius = self.attributes.rest.radius
113
- _text_color = self.attributes.rest.text_color
126
+ self.text.configure(state="disabled")
127
+ _back_color = self.attributes.disabled.back_color
128
+ _border_color = self.attributes.disabled.border_color
129
+ _border_color2 = self.attributes.disabled.border_color2
130
+ _border_width = self.attributes.disabled.border_width
131
+ _radius = self.attributes.disabled.radius
132
+ _text_color = self.attributes.disabled.text_color
114
133
 
115
134
  self.text.configure(
116
135
  background=_back_color, insertbackground=_text_color, foreground=_text_color,
@@ -123,6 +142,11 @@ class FluText(FluTextCanvas, DDrawWidget):
123
142
  fill=_back_color, outline=_border_color, outline2=_border_color2, width=_border_width
124
143
  )
125
144
 
145
+ self.element_line = self.create_line(
146
+ _radius / 3, self.winfo_height() - _radius / 3, self.winfo_width() - _radius / 3, self.winfo_height() - _radius / 3,
147
+ width=1, fill=_border_color2
148
+ )
149
+
126
150
  self.element_text = self.create_window(
127
151
  self.winfo_width() / 2, self.winfo_height() / 2,
128
152
  window=self.text,
@@ -151,7 +175,7 @@ class FluText(FluTextCanvas, DDrawWidget):
151
175
  self.dconfigure(
152
176
  rest={
153
177
  "back_color": "#ffffff",
154
- "border_color": "#f0f0f0",
178
+ "border_color": "#e5e5e5",
155
179
  "border_color2": "#8d8d8d",
156
180
  "border_width": 1,
157
181
  "radius": 6,
@@ -159,11 +183,19 @@ class FluText(FluTextCanvas, DDrawWidget):
159
183
  },
160
184
  focus={
161
185
  "back_color": "#ffffff",
162
- "border_color": "#f0f0f0",
186
+ "border_color": "#e5e5e5",
163
187
  "border_color2": "#005fb8",
164
188
  "border_width": 2,
165
189
  "radius": 6,
166
190
  "text_color": "#636363",
191
+ },
192
+ disabled={
193
+ "back_color": "#fdfdfd",
194
+ "border_color": "#e5e5e5",
195
+ "border_color2": "#e5e5e5",
196
+ "border_width": 1,
197
+ "radius": 6,
198
+ "text_color": "#a2a2a2",
167
199
  }
168
200
  )
169
201
 
@@ -184,5 +216,13 @@ class FluText(FluTextCanvas, DDrawWidget):
184
216
  "border_width": 2,
185
217
  "radius": 6,
186
218
  "text_color": "#ffffff",
219
+ },
220
+ disabled={
221
+ "back_color": "#2a2a2a",
222
+ "border_color": "#303030",
223
+ "border_color2": "#303030",
224
+ "border_width": 1,
225
+ "radius": 6,
226
+ "text_color": "#787878",
187
227
  }
188
- )
228
+ )
tkflu/thememanager.py CHANGED
@@ -1,8 +1,9 @@
1
1
  from .window import FluWindow
2
+ from .toplevel import FluToplevel
2
3
 
3
4
 
4
5
  class FluThemeManager(object):
5
- def __init__(self, window: FluWindow = None, mode: str = "light"):
6
+ def __init__(self, window=None, mode: str = "light"):
6
7
  if window:
7
8
  self._window = window
8
9
  else:
tkflu/togglebutton.py CHANGED
@@ -93,57 +93,15 @@ class FluToggleButton(FluToggleButtonCanvas, DDrawWidget):
93
93
  "checked": False,
94
94
 
95
95
  "uncheck": {
96
- "rest": {
97
- "back_color": None,
98
- "border_color": None,
99
- "border_color2": None,
100
- "border_width": None,
101
- "radius": None,
102
- "text_color": None,
103
- },
104
- "hover": {
105
- "back_color": None,
106
- "border_color": None,
107
- "border_color2": None,
108
- "border_width": None,
109
- "radius": None,
110
- "text_color": None,
111
- },
112
- "pressed": {
113
- "back_color": None,
114
- "border_color": None,
115
- "border_color2": None,
116
- "border_width": None,
117
- "radius": None,
118
- "text_color": None,
119
- }
96
+ "rest": {},
97
+ "hover": {},
98
+ "pressed": {}
120
99
  },
121
100
 
122
101
  "check": {
123
- "rest": {
124
- "back_color": None,
125
- "border_color": None,
126
- "border_color2": None,
127
- "border_width": None,
128
- "radius": None,
129
- "text_color": None,
130
- },
131
- "hover": {
132
- "back_color": None,
133
- "border_color": None,
134
- "border_color2": None,
135
- "border_width": None,
136
- "radius": None,
137
- "text_color": None,
138
- },
139
- "pressed": {
140
- "back_color": None,
141
- "border_color": None,
142
- "border_color2": None,
143
- "border_width": None,
144
- "radius": None,
145
- "text_color": None,
146
- }
102
+ "rest": {},
103
+ "hover": {},
104
+ "pressed": {}
147
105
  }
148
106
  }
149
107
  )
tkflu/tooltip.py ADDED
@@ -0,0 +1,8 @@
1
+ from .popupwindow import FluPopupWindow
2
+
3
+
4
+ class FluToolTip(FluPopupWindow):
5
+ def __init__(self, widget, *args, **kwargs):
6
+ super().__init__(*args, **kwargs)
7
+
8
+ self.widget = widget
tkflu/toplevel.py ADDED
@@ -0,0 +1,29 @@
1
+ from tkinter import Toplevel
2
+ from tkdeft.object import DObject
3
+ from .bwm import BWm
4
+
5
+
6
+ class FluToplevel(Toplevel, BWm, DObject):
7
+
8
+ """Fluent设计的子窗口"""
9
+
10
+ def __init__(self, *args, mode="light", **kwargs):
11
+
12
+ """
13
+ 初始化类
14
+
15
+ :param args: 参照tkinter.TK.__init__
16
+ :param className: 参照tkinter.TK.__init__
17
+ :param mode: Fluent主题模式 分为 “light” “dark”
18
+ :param kwargs: 参照tkinter.TK.__init__
19
+ """
20
+
21
+ self._init(mode)
22
+
23
+ self.custom = False
24
+
25
+ Toplevel.__init__(self, *args, **kwargs)
26
+
27
+ self.bind("<Configure>", self._event_configure, add="+")
28
+ self.bind("<Escape>", self._event_key_esc, add="+")
29
+ self.protocol("WM_DELETE_WINDOW", self._event_delete_window)
tkflu/window.py CHANGED
@@ -1,8 +1,9 @@
1
- from tkinter import Tk
1
+ from tkinter import Tk, Toplevel
2
2
  from tkdeft.object import DObject
3
+ from .bwm import BWm
3
4
 
4
5
 
5
- class FluWindow(Tk, DObject):
6
+ class FluWindow(Tk, BWm, DObject):
6
7
 
7
8
  """Fluent设计的主窗口"""
8
9
 
@@ -23,175 +24,11 @@ class FluWindow(Tk, DObject):
23
24
 
24
25
  super().__init__(*args, className=className, **kwargs)
25
26
 
26
- self.bind("<Configure>", self._event_configure)
27
+ from .icons import light
28
+ from tkinter import PhotoImage
27
29
 
28
- def _draw(self, event=None):
30
+ self.iconphoto(False, PhotoImage(file=light()))
29
31
 
30
- """
31
- 重新绘制窗口及自定义的窗口组件
32
-
33
- :param event:
34
- """
35
-
36
- self.configure(background=self.attributes.back_color)
37
- if self.custom:
38
- if hasattr(self, "titlebar"):
39
- self.titlebar.configure(background=self.attributes.back_color)
40
- self.titlebar.update()
41
- if hasattr(self, "titlelabel"):
42
- self.titlelabel.dconfigure(text_color=self.attributes.text_color)
43
- self.titlelabel._draw()
44
- if hasattr(self, "closebutton"):
45
- self.closebutton.dconfigure(
46
- rest={
47
- "back_color": self.titlebar.cget("background"),
48
- "border_color": "#f0f0f0",
49
- "border_color2": "#d6d6d6",
50
- "border_width": 0,
51
- "radius": 0,
52
- "text_color": self.attributes.closebutton.text_color,
53
- },
54
- hover={
55
- "back_color": self.attributes.closebutton.back_color,
56
- "border_color": "#f0f0f0",
57
- "border_color2": "#d6d6d6",
58
- "border_width": 0,
59
- "radius": 0,
60
- "text_color": self.attributes.closebutton.text_hover_color,
61
- },
62
- pressed={
63
- "back_color": self.attributes.closebutton.back_color,
64
- "border_color": "#f0f0f0",
65
- "border_color2": "#f0f0f0",
66
- "border_width": 0,
67
- "radius": 0,
68
- "text_color": self.attributes.closebutton.text_hover_color,
69
- }
70
- )
71
- self.closebutton._draw()
72
-
73
- def _event_configure(self, event=None):
74
-
75
- """
76
- 触发 `<Configure>` 事件
77
-
78
- :param event:
79
- :return:
80
- """
81
-
82
- self._draw()
83
-
84
- def _init(self, mode):
85
- from easydict import EasyDict
86
- self.attributes = EasyDict(
87
- {
88
- "back_color": None,
89
- "text_color": None,
90
- "closebutton": {
91
- "back_color": None,
92
- "text_color": None,
93
- "text_hover_color": None
94
- }
95
- }
96
- )
97
-
98
- self.theme(mode)
99
-
100
- def theme(self, mode: str):
101
-
102
- """
103
- 同 `theme_myself`
104
-
105
- :param mode:
106
- :return:
107
- """
108
-
109
- self.theme_myself(mode=mode)
110
-
111
- def theme_myself(self, mode: str):
112
-
113
- """
114
- 修改该窗口的Fluent主题
115
-
116
- :param mode:
117
- :return:
118
- """
119
-
120
- self.mode = mode
121
- if mode.lower() == "dark":
122
- self._dark()
123
- else:
124
- self._light()
125
-
126
- def _light(self):
127
- self.dconfigure(
128
- back_color="#ffffff",
129
- text_color="#000000",
130
- closebutton={
131
- "back_color": "red",
132
- "text_color": "#000000",
133
- "text_hover_color": "#ffffff"
134
- }
135
- )
136
-
137
- def _dark(self):
138
- self.dconfigure(
139
- back_color="#202020",
140
- text_color="#ffffff",
141
- closebutton={
142
- "back_color": "red",
143
- "text_color": "#ffffff",
144
- "text_hover_color": "#000000"
145
- }
146
- )
147
-
148
- def wincustom(self, wait=200, way=1):
149
-
150
- """
151
- 自定义窗口 仅限`Windows系统`
152
-
153
- :param wait: 直接执行自定义窗口容易出错误 需要一点时间等待才能执行 同`after()`中的`ms`
154
- :param way: 取0时保留原版边框,但稳定性很差,容易崩溃。取1时不保留原版边框,但稳定性较好。
155
- :return:
156
- """
157
-
158
- from sys import platform
159
- from .button import FluButton
160
- from .label import FluLabel
161
- from tkinter import Frame
162
- self.titlebar = Frame(self, width=180, height=35, background=self.attributes.back_color)
163
- self.titlelabel = FluLabel(self.titlebar, text=self.title(), width=50)
164
- self.titlelabel.pack(fill="y", side="left")
165
- self.closebutton = FluButton(self.titlebar, text="", width=32, height=32, command=lambda: self.quit())
166
- self.closebutton.pack(fill="y", side="right")
167
- self.titlebar.pack(fill="x", side="top")
168
-
169
- if platform == "win32":
170
- if way == 0:
171
- from .customwindow import CustomWindow
172
- self.customwindow = CustomWindow(self, wait=wait)
173
- self.customwindow.bind_drag(self.titlebar)
174
- self.customwindow.bind_drag(self.titlelabel)
175
- else:
176
- self.overrideredirect(True)
177
- try:
178
- from win32gui import GetParent, GetWindowLong, SetWindowLong
179
- from win32con import GWL_EXSTYLE, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW
180
- hwnd = GetParent(self.winfo_id())
181
- style = GetWindowLong(hwnd, GWL_EXSTYLE)
182
- style = style & ~WS_EX_TOOLWINDOW
183
- style = style | WS_EX_APPWINDOW
184
- SetWindowLong(hwnd, GWL_EXSTYLE, style)
185
- self.after(30, lambda: self.withdraw())
186
- self.after(60, lambda: self.deiconify())
187
- except:
188
- pass
189
-
190
- self.wm_attributes("-topmost", True)
191
-
192
- from .customwindow2 import WindowDragArea
193
- self.dragarea = WindowDragArea(self)
194
- self.dragarea.bind(self.titlebar)
195
- self.dragarea.bind(self.titlelabel)
196
-
197
- self.custom = True
32
+ self.bind("<Configure>", self._event_configure, add="+")
33
+ self.bind("<Escape>", self._event_key_esc, add="+")
34
+ self.protocol("WM_DELETE_WINDOW", self._event_delete_window)