restructured color changing with configure methods

This commit is contained in:
Tom Schimansky 2021-11-06 22:06:27 +01:00
parent f7d4f902a9
commit a6e8e52710
8 changed files with 193 additions and 151 deletions

View File

@ -167,14 +167,15 @@ compound | set image orientation if image and text are given ("top", "left", "bo
state | tkinter.NORMAL (standard) or tkinter.DISABLED (not clickable, darker color)
CTkButton Methods:
```python
CTkButton.set_text(new_text)
CTkButton.change_image(new_image)
CTkButton.configure_color(bg_color=new_bg_color,
CTkButton.set_image(new_image)
CTkButton.configure(text=new_text)
CTkButton.configure(bg_color=new_bg_color,
fg_color=new_fg_color,
hover_color=new_hover_color,
text_color=new_text_color)
CTkButton.configure(state=tkinter.DISABLED)
CTkButton.configure(state=tkinter.NORMAL)
button_state = CTkButton.state
@ -203,7 +204,7 @@ width | label width in px
height | label height in px
corner_radius | corner radius in px
fg_color | forground color, tuple: (light_color, dark_color) or single color
bg_color | background color, tuple: (light_color, dark_color) or single color
bg_color | background color, tuple: (light_color, dark_color) or single color, None for transparent bg
text_color | label text color, tuple: (light_color, dark_color) or single color
text_font | label text font, tuple: (font_name, size)
</details>
@ -265,15 +266,14 @@ state | tkinter.NORMAL (standard) or tkinter.DISABLED (not clickable, darker col
CTkCheckBox Methods:
```python
CTkCheckBox.get() # 1 or 0 (checked or not checked)
CTkCheckBox.set_text(new_text)
CTkCheckBox.select() # turns on checkbox
CTkCheckBox.deselect() # turns off checkbox
CTkCheckBox.toggle() # change check state of checkbox
CTkCheckBox.configure_color(bg_color=new_bg_color,
CTkCheckBox.configure(text=new_text)
CTkCheckBox.configure(bg_color=new_bg_color,
fg_color=new_fg_color,
hover_color=new_hover_color,
text_color=new_text_color)
CTkCheckBox.configure(state=tkinter.DISABLED)
CTkCheckBox.configure(state=tkinter.NORMAL)
checkbox_state = CTkCheckBox.state

View File

@ -34,17 +34,10 @@ class CTkButton(tkinter.Frame):
self.configure_basic_grid()
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.hover_color = self.bg_color if hover_color is None else hover_color
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
self.fg_color = self.bg_color if fg_color is None else fg_color
self.fg_color = self.bg_color if self.fg_color is None else self.fg_color
self.hover_color = self.fg_color if hover_color is None else hover_color
self.border_color = border_color
self.width = width
@ -72,7 +65,7 @@ class CTkButton(tkinter.Frame):
elif "win" in sys.platform: # Windows
self.text_font = ("Century Gothic", 11)
else:
self.text_font = ("TkDefaultFont")
self.text_font = "TkDefaultFont"
else:
self.text_font = text_font
@ -123,6 +116,12 @@ class CTkButton(tkinter.Frame):
self.height = event.height
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
self.canvas.delete("all")
self.canvas_fg_parts = []
@ -132,19 +131,24 @@ class CTkButton(tkinter.Frame):
# create border button parts
if self.border_width > 0:
if self.corner_radius > 0:
self.canvas_border_parts.append(self.canvas.create_oval(0,
self.canvas_border_parts.append(self.canvas.create_oval(0, 0, 0, 0))
self.canvas_border_parts.append(self.canvas.create_oval(0, 0, 0, 0))
self.canvas_border_parts.append(self.canvas.create_oval(0, 0, 0, 0))
#self.canvas_border_parts.append(self.canvas.create_oval(0, 0, 0, 0))
self.canvas.itemconfig(self.canvas_border_parts[0], (0,
0,
self.corner_radius * 2,
self.corner_radius * 2))
self.canvas_border_parts.append(self.canvas.create_oval(self.width - self.corner_radius * 2,
self.canvas.itemconfig(self.canvas_border_parts[0], (self.width - self.corner_radius * 2,
0,
self.width,
self.corner_radius * 2))
self.canvas_border_parts.append(self.canvas.create_oval(0,
self.canvas.itemconfig(self.canvas_border_parts[0], (0,
self.height - self.corner_radius * 2,
self.corner_radius * 2,
self.height))
self.canvas_border_parts.append(self.canvas.create_oval(self.width - self.corner_radius * 2,
self.canvas.itemconfig(self.canvas_border_parts[0], (self.width - self.corner_radius * 2,
self.height - self.corner_radius * 2,
self.width,
self.height))
@ -219,7 +223,7 @@ class CTkButton(tkinter.Frame):
self.set_text(self.text)
# use image for button if given
# create image label if image given
if self.image is not None:
self.image_label = tkinter.Label(master=self, image=self.image)
@ -257,27 +261,12 @@ class CTkButton(tkinter.Frame):
self.image_label.grid(row=1, column=0, padx=self.corner_radius, sticky="n", columnspan=2)
self.text_label.grid(row=0, column=0, padx=self.corner_radius, sticky="s", columnspan=2)
def configure_color(self, bg_color=None, fg_color=None, hover_color=None, text_color=None):
if bg_color is not None:
self.bg_color = bg_color
else:
self.bg_color = self.master.cget("bg")
if fg_color is not None:
self.fg_color = fg_color
if hover_color is not None:
self.hover_color = hover_color
if text_color is not None:
self.text_color = text_color
self.draw()
def config(self, *args, **kwargs):
self.configure(*args, **kwargs)
def configure(self, *args, **kwargs):
require_redraw = False # some attribute changes require a call of self.draw() at the end
if "text" in kwargs:
self.set_text(kwargs["text"])
del kwargs["text"]
@ -286,8 +275,38 @@ class CTkButton(tkinter.Frame):
self.set_state(kwargs["state"])
del kwargs["state"]
if "image" in kwargs:
self.set_image(kwargs["image"])
del kwargs["image"]
if "fg_color" in kwargs:
self.fg_color = kwargs["fg_color"]
require_redraw = True
del kwargs["fg_color"]
if "bg_color" in kwargs:
if kwargs["bg_color"] is None:
self.bg_color = self.detect_color_of_master()
else:
self.bg_color = kwargs["bg_color"]
require_redraw = True
del kwargs["bg_color"]
if "hover_color" in kwargs:
self.hover_color = kwargs["hover_color"]
require_redraw = True
del kwargs["hover_color"]
if "text_color" in kwargs:
self.text_color = kwargs["text_color"]
require_redraw = True
del kwargs["text_color"]
super().configure(*args, **kwargs)
if require_redraw:
self.draw()
def set_state(self, state):
self.state = state
@ -310,7 +329,7 @@ class CTkButton(tkinter.Frame):
else:
sys.stderr.write("ERROR (CTkButton): Cant change text because button has no text.")
def change_image(self, image):
def set_image(self, image):
if self.image_label is not None:
self.image = image
self.image_label.configure(image=self.image)
@ -319,43 +338,31 @@ class CTkButton(tkinter.Frame):
def on_enter(self, event=0):
if self.hover is True:
# set color of inner button parts to hover color
for part in self.canvas_fg_parts:
if type(self.hover_color) == tuple and len(self.hover_color) == 2:
self.canvas.itemconfig(part, fill=self.hover_color[self.appearance_mode], width=0)
else:
self.canvas.itemconfig(part, fill=self.hover_color, width=0)
self.canvas.itemconfig(part, fill=CTkColorManager.single_color(self.hover_color, self.appearance_mode), width=0)
# set text_label bg color to button hover color
if self.text_label is not None:
if type(self.hover_color) == tuple and len(self.hover_color) == 2:
self.text_label.configure(bg=self.hover_color[self.appearance_mode])
else:
self.text_label.configure(bg=self.hover_color)
self.text_label.configure(bg=CTkColorManager.single_color(self.hover_color, self.appearance_mode))
# set image_label bg color to button hover color
if self.image_label is not None:
if type(self.hover_color) == tuple and len(self.hover_color) == 2:
self.image_label.configure(bg=self.hover_color[self.appearance_mode])
else:
self.image_label.configure(bg=self.hover_color)
self.image_label.configure(bg=CTkColorManager.single_color(self.hover_color, self.appearance_mode))
def on_leave(self, event=0):
if self.hover is True:
# set color of inner button parts
for part in self.canvas_fg_parts:
if type(self.fg_color) == tuple and len(self.fg_color) == 2:
self.canvas.itemconfig(part, fill=self.fg_color[self.appearance_mode], width=0)
else:
self.canvas.itemconfig(part, fill=self.fg_color, width=0)
self.canvas.itemconfig(part, fill=CTkColorManager.single_color(self.fg_color, self.appearance_mode), width=0)
# set text_label bg color (label color)
if self.text_label is not None:
if type(self.fg_color) == tuple and len(self.fg_color) == 2:
self.text_label.configure(bg=self.fg_color[self.appearance_mode])
else:
self.text_label.configure(bg=self.fg_color)
self.text_label.configure(bg=CTkColorManager.single_color(self.fg_color, self.appearance_mode))
# set image_label bg color (image bg color)
if self.image_label is not None:
if type(self.fg_color) == tuple and len(self.fg_color) == 2:
self.image_label.configure(bg=self.fg_color[self.appearance_mode])
else:
self.image_label.configure(bg=self.fg_color)
self.image_label.configure(bg=CTkColorManager.single_color(self.fg_color, self.appearance_mode))
def clicked(self, event=0):
if self.function is not None:

View File

@ -28,21 +28,13 @@ class CTkCheckBox(tkinter.Frame):
super().__init__(*args, **kwargs)
AppearanceModeTracker.add(self.set_appearance_mode)
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
self.fg_color = CTkColorManager.MAIN if fg_color is None else fg_color
self.hover_color = CTkColorManager.MAIN_HOVER if hover_color is None else hover_color
self.border_color = border_color
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.width = width
self.height = height
@ -100,6 +92,12 @@ class CTkCheckBox(tkinter.Frame):
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
self.canvas.delete("all")
self.canvas_fg_parts = []
@ -195,7 +193,7 @@ class CTkCheckBox(tkinter.Frame):
else:
self.text_label.configure(fg=self.text_color)
if type(self.bg_color) == tuple and len(self.text_color) == 2:
if type(self.bg_color) == tuple and len(self.bg_color) == 2:
self.configure(bg=self.bg_color[self.appearance_mode])
self.text_label.configure(bg=self.bg_color[self.appearance_mode])
else:
@ -204,27 +202,12 @@ class CTkCheckBox(tkinter.Frame):
self.set_text(self.text)
def configure_color(self, bg_color=None, fg_color=None, hover_color=None, text_color=None):
if bg_color is not None:
self.bg_color = bg_color
else:
self.bg_color = self.master.cget("bg")
if fg_color is not None:
self.fg_color = fg_color
if hover_color is not None:
self.hover_color = hover_color
if text_color is not None:
self.text_color = text_color
self.draw()
def config(self, *args, **kwargs):
self.configure(*args, **kwargs)
def configure(self, *args, **kwargs):
require_redraw = False # some attribute changes require a call of self.draw()
if "text" in kwargs:
self.set_text(kwargs["text"])
del kwargs["text"]
@ -233,8 +216,39 @@ class CTkCheckBox(tkinter.Frame):
self.set_state(kwargs["state"])
del kwargs["state"]
if "fg_color" in kwargs:
self.fg_color = kwargs["fg_color"]
require_redraw = True
del kwargs["fg_color"]
if "bg_color" in kwargs:
if kwargs["bg_color"] is None:
self.bg_color = self.detect_color_of_master()
else:
self.bg_color = kwargs["bg_color"]
require_redraw = True
del kwargs["bg_color"]
if "hover_color" in kwargs:
self.hover_color = kwargs["hover_color"]
require_redraw = True
del kwargs["hover_color"]
if "text_color" in kwargs:
self.text_color = kwargs["text_color"]
require_redraw = True
del kwargs["text_color"]
if "border_color" in kwargs:
self.border_color = kwargs["border_color"]
require_redraw = True
del kwargs["border_color"]
super().configure(*args, **kwargs)
if require_redraw:
self.draw()
def set_state(self, state):
self.state = state

View File

@ -19,19 +19,12 @@ class CTkEntry(tkinter.Frame):
super().__init__(master=master)
AppearanceModeTracker.add(self.change_appearance_mode)
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.fg_color = fg_color
self.text_color = text_color
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
self.fg_color = self.bg_color if fg_color is None else fg_color
self.text_color = text_color
self.width = width
self.height = height
self.corner_radius = corner_radius
@ -54,6 +47,12 @@ class CTkEntry(tkinter.Frame):
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
self.canvas.delete("all")
self.fg_parts = []

View File

@ -15,14 +15,9 @@ class CTkFrame(tkinter.Frame):
super().__init__(*args, **kwargs)
AppearanceModeTracker.add(self.change_appearance_mode)
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
if fg_color is None:
if isinstance(self.master, CTkFrame):
@ -35,8 +30,6 @@ class CTkFrame(tkinter.Frame):
else:
self.fg_color = fg_color
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.width = width
self.height = height
self.corner_radius = corner_radius
@ -47,20 +40,24 @@ class CTkFrame(tkinter.Frame):
highlightthicknes=0,
width=self.width,
height=self.height)
self.canvas.place(x=0, y=0)
if type(self.bg_color) == tuple:
self.canvas.configure(bg=self.bg_color[self.appearance_mode])
else:
self.canvas.configure(bg=self.bg_color)
self.canvas.place(x=0, y=0)
self.fg_parts = []
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
#self.canvas.delete("all")
for part in self.fg_parts:
self.canvas.delete(part)
self.fg_parts = []

View File

@ -22,18 +22,11 @@ class CTkLabel(tkinter.Frame):
super().__init__(master=master)
AppearanceModeTracker.add(self.change_appearance_mode)
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
self.fg_color = self.bg_color if fg_color is None else fg_color
self.text_color = text_color
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.width = width
self.height = height
@ -69,6 +62,12 @@ class CTkLabel(tkinter.Frame):
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
self.canvas.delete("all")
self.fg_parts = []
@ -121,6 +120,36 @@ class CTkLabel(tkinter.Frame):
self.draw()
def configure(self, *args, **kwargs):
require_redraw = False # some attribute changes require a call of self.draw() at the end
if "text" in kwargs:
self.set_text(kwargs["text"])
del kwargs["text"]
if "fg_color" in kwargs:
self.fg_color = kwargs["fg_color"]
require_redraw = True
del kwargs["fg_color"]
if "bg_color" in kwargs:
if kwargs["bg_color"] is None:
self.bg_color = self.detect_color_of_master()
else:
self.bg_color = kwargs["bg_color"]
require_redraw = True
del kwargs["bg_color"]
if "text_color" in kwargs:
self.text_color = kwargs["text_color"]
require_redraw = True
del kwargs["text_color"]
super().configure(*args, **kwargs)
if require_redraw:
self.draw()
def set_text(self, text):
self.text = text
self.text_label.configure(text=self.text, width=len(self.text))

View File

@ -20,21 +20,13 @@ class CTkProgressBar(tkinter.Frame):
super().__init__(*args, **kwargs)
AppearanceModeTracker.add(self.change_appearance_mode)
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
self.border_color = border_color
self.fg_color = fg_color
self.progress_color = CTkColorManager.MAIN if progress_color is None else progress_color
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.width = width
self.height = height
self.border_width = border_width
@ -54,6 +46,12 @@ class CTkProgressBar(tkinter.Frame):
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
self.canvas.delete("all")
self.border_parts = []

View File

@ -25,27 +25,19 @@ class CTkSlider(tkinter.Frame):
super().__init__(*args, **kwargs)
AppearanceModeTracker.add(self.change_appearance_mode)
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
if bg_color is None:
if isinstance(self.master, CTkFrame):
self.bg_color = self.master.fg_color
else:
self.bg_color = self.master.cget("bg")
else:
self.bg_color = bg_color
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
self.border_color = border_color
self.fg_color = fg_color
self.button_color = self.bg_color if button_color is None else button_color
self.button_hover_color = self.bg_color if button_hover_color is None else button_hover_color
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.width = width
self.height = height
self.border_width = border_width
self.callback_function = command
self.value = 0.5
self.value = 0.5 # initial value of slider in percent
self.hover_state = False
self.from_ = from_
self.to = to
@ -72,6 +64,12 @@ class CTkSlider(tkinter.Frame):
self.draw()
def detect_color_of_master(self):
if isinstance(self.master, CTkFrame):
return self.master.fg_color
else:
return self.master.cget("bg")
def draw(self):
self.canvas.delete("all")
self.border_parts = []