mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
added compound to CTkButton, restructured some code in CTkButton for better readability
This commit is contained in:
parent
ba1bf8c4b8
commit
02abcac558
@ -161,6 +161,7 @@ text_color | text color, tuple: (light_color, dark_color) or single color
|
|||||||
text_font | button text font, tuple: (font_name, size)
|
text_font | button text font, tuple: (font_name, size)
|
||||||
hover | enable/disable hover effect: True, False
|
hover | enable/disable hover effect: True, False
|
||||||
image | put an image on the button, removes the text, must be class PhotoImage
|
image | put an image on the button, removes the text, must be class PhotoImage
|
||||||
|
compound | set image orientation if image and text are given ("top", "left", "bottom", "right")
|
||||||
state | tkinter.NORMAL (standard) or tkinter.DISABLED (not clickable, darker color)
|
state | tkinter.NORMAL (standard) or tkinter.DISABLED (not clickable, darker color)
|
||||||
|
|
||||||
CTkButton Methods:
|
CTkButton Methods:
|
||||||
|
@ -24,11 +24,13 @@ class CTkButton(tkinter.Frame):
|
|||||||
text="CTkButton",
|
text="CTkButton",
|
||||||
hover=True,
|
hover=True,
|
||||||
image=None,
|
image=None,
|
||||||
|
compound=tkinter.LEFT,
|
||||||
state=tkinter.NORMAL,
|
state=tkinter.NORMAL,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
AppearanceModeTracker.add(self.set_appearance_mode)
|
AppearanceModeTracker.add(self.set_appearance_mode)
|
||||||
|
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||||
|
|
||||||
self.configure_basic_grid()
|
self.configure_basic_grid()
|
||||||
|
|
||||||
@ -40,13 +42,10 @@ class CTkButton(tkinter.Frame):
|
|||||||
else:
|
else:
|
||||||
self.bg_color = bg_color
|
self.bg_color = bg_color
|
||||||
|
|
||||||
self.fg_color = self.bg_color if fg_color is None else fg_color
|
|
||||||
self.hover_color = self.bg_color if hover_color is None else hover_color
|
self.hover_color = self.bg_color if hover_color is None else hover_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.fg_color = self.bg_color if self.fg_color is None else self.fg_color
|
||||||
|
|
||||||
self.border_color = border_color
|
self.border_color = border_color
|
||||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
|
||||||
|
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
@ -81,17 +80,18 @@ class CTkButton(tkinter.Frame):
|
|||||||
self.state = state
|
self.state = state
|
||||||
self.hover = hover
|
self.hover = hover
|
||||||
self.image = image
|
self.image = image
|
||||||
|
self.compound = compound
|
||||||
|
|
||||||
self.configure(width=self.width, height=self.height)
|
self.configure(width=self.width, height=self.height)
|
||||||
|
|
||||||
if sys.platform == "darwin" and self.function is not None:
|
if sys.platform == "darwin" and self.function is not None:
|
||||||
self.configure(cursor="pointinghand")
|
self.configure(cursor="pointinghand") # other cursor when hovering over button with command
|
||||||
|
|
||||||
self.canvas = tkinter.Canvas(master=self,
|
self.canvas = tkinter.Canvas(master=self,
|
||||||
highlightthicknes=0,
|
highlightthicknes=0,
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=self.height)
|
height=self.height)
|
||||||
self.canvas.grid(row=0, column=0)
|
self.canvas.grid(row=0, column=0, rowspan=2, columnspan=2)
|
||||||
|
|
||||||
if self.hover is True:
|
if self.hover is True:
|
||||||
self.canvas.bind("<Enter>", self.on_enter)
|
self.canvas.bind("<Enter>", self.on_enter)
|
||||||
@ -110,9 +110,11 @@ class CTkButton(tkinter.Frame):
|
|||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def configure_basic_grid(self):
|
def configure_basic_grid(self):
|
||||||
# Configuration of a basic grid in which all elements of CTkButtons are centered on one row and one column
|
# Configuration of a basic grid (2x2) in which all elements of CTkButtons are centered on one row and one column
|
||||||
self.grid_rowconfigure(0, weight=1)
|
self.grid_rowconfigure(0, weight=1)
|
||||||
self.grid_columnconfigure(0, weight=1)
|
self.grid_columnconfigure(0, weight=1)
|
||||||
|
self.grid_rowconfigure(1, weight=1)
|
||||||
|
self.grid_columnconfigure(1, weight=1)
|
||||||
|
|
||||||
def update_dimensions(self, event):
|
def update_dimensions(self, event):
|
||||||
# We update the dimensions of the internal elements of CTkButton Widget
|
# We update the dimensions of the internal elements of CTkButton Widget
|
||||||
@ -125,15 +127,10 @@ class CTkButton(tkinter.Frame):
|
|||||||
self.canvas.delete("all")
|
self.canvas.delete("all")
|
||||||
self.canvas_fg_parts = []
|
self.canvas_fg_parts = []
|
||||||
self.canvas_border_parts = []
|
self.canvas_border_parts = []
|
||||||
|
self.canvas.configure(bg=CTkColorManager.single_color(self.bg_color, self.appearance_mode))
|
||||||
|
|
||||||
if type(self.bg_color) == tuple and len(self.bg_color) == 2:
|
# create border button parts
|
||||||
self.canvas.configure(bg=self.bg_color[self.appearance_mode])
|
|
||||||
else:
|
|
||||||
self.canvas.configure(bg=self.bg_color)
|
|
||||||
|
|
||||||
# border button parts
|
|
||||||
if self.border_width > 0:
|
if self.border_width > 0:
|
||||||
|
|
||||||
if self.corner_radius > 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,
|
||||||
@ -161,8 +158,7 @@ class CTkButton(tkinter.Frame):
|
|||||||
self.width - self.corner_radius,
|
self.width - self.corner_radius,
|
||||||
self.height))
|
self.height))
|
||||||
|
|
||||||
# inner button parts
|
# create inner button parts
|
||||||
|
|
||||||
if self.corner_radius > 0:
|
if self.corner_radius > 0:
|
||||||
self.canvas_fg_parts.append(self.canvas.create_oval(self.border_width,
|
self.canvas_fg_parts.append(self.canvas.create_oval(self.border_width,
|
||||||
self.border_width,
|
self.border_width,
|
||||||
@ -190,80 +186,76 @@ class CTkButton(tkinter.Frame):
|
|||||||
self.width - self.border_width,
|
self.width - self.border_width,
|
||||||
self.height - self.inner_corner_radius - self.border_width))
|
self.height - self.inner_corner_radius - self.border_width))
|
||||||
|
|
||||||
|
# set color for inner button parts
|
||||||
for part in self.canvas_fg_parts:
|
for part in self.canvas_fg_parts:
|
||||||
if type(self.fg_color) == tuple and len(self.fg_color) == 2:
|
if self.state == tkinter.DISABLED:
|
||||||
if self.state == tkinter.DISABLED:
|
self.canvas.itemconfig(part,
|
||||||
self.canvas.itemconfig(part,
|
fill=CTkColorManager.darken_hex_color(CTkColorManager.single_color(self.fg_color, self.appearance_mode)),
|
||||||
fill=CTkColorManager.darken_hex_color(self.fg_color[self.appearance_mode]), width=0)
|
width=0)
|
||||||
else:
|
|
||||||
self.canvas.itemconfig(part, fill=self.fg_color[self.appearance_mode], width=0)
|
|
||||||
else:
|
else:
|
||||||
if self.state == tkinter.DISABLED:
|
self.canvas.itemconfig(part, fill=CTkColorManager.single_color(self.fg_color, self.appearance_mode), width=0)
|
||||||
self.canvas.itemconfig(part,
|
|
||||||
fill=CTkColorManager.darken_hex_color(self.fg_color),
|
|
||||||
outline=self.fg_color, width=0)
|
|
||||||
else:
|
|
||||||
self.canvas.itemconfig(part, fill=self.fg_color, outline=self.fg_color, width=0)
|
|
||||||
|
|
||||||
|
# set color for the button border parts (outline)
|
||||||
for part in self.canvas_border_parts:
|
for part in self.canvas_border_parts:
|
||||||
if type(self.border_color) == tuple and len(self.border_color) == 2:
|
self.canvas.itemconfig(part, fill=CTkColorManager.single_color(self.border_color, self.appearance_mode), width=0)
|
||||||
self.canvas.itemconfig(part, fill=self.border_color[self.appearance_mode], width=0)
|
|
||||||
else:
|
|
||||||
self.canvas.itemconfig(part, fill=self.border_color, outline=self.border_color, width=0)
|
|
||||||
|
|
||||||
# no image provided
|
# create text label if text given
|
||||||
if self.image is None:
|
if self.text is not None and self.text != "":
|
||||||
self.text_label = tkinter.Label(master=self,
|
self.text_label = tkinter.Label(master=self, text=self.text, font=self.text_font)
|
||||||
text=self.text,
|
|
||||||
font=self.text_font)
|
|
||||||
self.text_label.grid(row=0, column=0, padx=self.corner_radius)
|
|
||||||
|
|
||||||
self.text_label.bind("<Enter>", self.on_enter)
|
self.text_label.bind("<Enter>", self.on_enter)
|
||||||
self.text_label.bind("<Leave>", self.on_leave)
|
self.text_label.bind("<Leave>", self.on_leave)
|
||||||
|
|
||||||
self.text_label.bind("<Button-1>", self.clicked)
|
self.text_label.bind("<Button-1>", self.clicked)
|
||||||
self.text_label.bind("<Button-1>", self.clicked)
|
self.text_label.bind("<Button-1>", self.clicked)
|
||||||
|
|
||||||
if type(self.text_color) == tuple and len(self.text_color) == 2:
|
# set text_label fg color (text color)
|
||||||
self.text_label.configure(fg=self.text_color[self.appearance_mode])
|
self.text_label.configure(fg=CTkColorManager.single_color(self.text_color, self.appearance_mode))
|
||||||
else:
|
|
||||||
self.text_label.configure(fg=self.text_color)
|
|
||||||
|
|
||||||
if type(self.fg_color) == tuple and len(self.fg_color) == 2:
|
# set text_label bg color (label color)
|
||||||
if self.state == tkinter.DISABLED:
|
if self.state == tkinter.DISABLED:
|
||||||
self.text_label.configure(bg=CTkColorManager.darken_hex_color(self.fg_color[self.appearance_mode]))
|
self.text_label.configure(bg=CTkColorManager.darken_hex_color(CTkColorManager.single_color(self.fg_color, self.appearance_mode)))
|
||||||
else:
|
|
||||||
self.text_label.configure(bg=self.fg_color[self.appearance_mode])
|
|
||||||
else:
|
else:
|
||||||
if self.state == tkinter.DISABLED:
|
self.text_label.configure(bg=CTkColorManager.single_color(self.fg_color, self.appearance_mode))
|
||||||
self.text_label.configure(bg=CTkColorManager.darken_hex_color(self.fg_color))
|
|
||||||
else:
|
|
||||||
self.text_label.configure(bg=self.fg_color)
|
|
||||||
|
|
||||||
self.set_text(self.text)
|
self.set_text(self.text)
|
||||||
|
|
||||||
# use image for button
|
# use image for button if given
|
||||||
else:
|
if self.image is not None:
|
||||||
self.image_label = tkinter.Label(master=self,
|
self.image_label = tkinter.Label(master=self, image=self.image)
|
||||||
image=self.image)
|
|
||||||
self.image_label.grid(row=0, column=0)
|
|
||||||
|
|
||||||
self.image_label.bind("<Enter>", self.on_enter)
|
self.image_label.bind("<Enter>", self.on_enter)
|
||||||
self.image_label.bind("<Leave>", self.on_leave)
|
self.image_label.bind("<Leave>", self.on_leave)
|
||||||
|
|
||||||
self.image_label.bind("<Button-1>", self.clicked)
|
self.image_label.bind("<Button-1>", self.clicked)
|
||||||
self.image_label.bind("<Button-1>", self.clicked)
|
self.image_label.bind("<Button-1>", self.clicked)
|
||||||
|
|
||||||
if type(self.fg_color) == tuple and len(self.fg_color) == 2:
|
# set image_label bg color (background color of label)
|
||||||
if self.state == tkinter.DISABLED:
|
if self.state == tkinter.DISABLED:
|
||||||
self.image_label.configure(bg=CTkColorManager.darken_hex_color(self.fg_color[self.appearance_mode]))
|
self.image_label.configure(bg=CTkColorManager.darken_hex_color(CTkColorManager.single_color(self.fg_color, self.appearance_mode)))
|
||||||
else:
|
|
||||||
self.image_label.configure(bg=self.fg_color[self.appearance_mode])
|
|
||||||
else:
|
else:
|
||||||
if self.state == tkinter.DISABLED:
|
self.image_label.configure(bg=CTkColorManager.single_color(self.fg_color, self.appearance_mode))
|
||||||
self.image_label.configure(bg=CTkColorManager.darken_hex_color(self.fg_color))
|
|
||||||
else:
|
# create grid layout with just an image given
|
||||||
self.image_label.configure(bg=self.fg_color)
|
if self.image_label is not None and self.text_label is None:
|
||||||
|
self.image_label.grid(row=0, column=0, rowspan=2, columnspan=2)
|
||||||
|
|
||||||
|
# create grid layout with just text given
|
||||||
|
if self.image_label is None and self.text_label is not None:
|
||||||
|
self.text_label.grid(row=0, column=0, padx=self.corner_radius, rowspan=2, columnspan=2)
|
||||||
|
|
||||||
|
# create grid layout of image and text label in 2x2 grid system with given compound
|
||||||
|
if self.image_label is not None and self.text_label is not None:
|
||||||
|
if self.compound == tkinter.LEFT or self.compound == "left":
|
||||||
|
self.image_label.grid(row=0, column=0, padx=self.corner_radius, sticky="e", rowspan=2)
|
||||||
|
self.text_label.grid(row=0, column=1, padx=self.corner_radius, sticky="w", rowspan=2)
|
||||||
|
elif self.compound == tkinter.TOP or self.compound == "top":
|
||||||
|
self.image_label.grid(row=0, column=0, padx=self.corner_radius, sticky="s", columnspan=2)
|
||||||
|
self.text_label.grid(row=1, column=0, padx=self.corner_radius, sticky="n", columnspan=2)
|
||||||
|
elif self.compound == tkinter.RIGHT or self.compound == "right":
|
||||||
|
self.image_label.grid(row=0, column=1, padx=self.corner_radius, sticky="w", rowspan=2)
|
||||||
|
self.text_label.grid(row=0, column=0, padx=self.corner_radius, sticky="e", rowspan=2)
|
||||||
|
elif self.compound == tkinter.BOTTOM or self.compound == "bottom":
|
||||||
|
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):
|
def configure_color(self, bg_color=None, fg_color=None, hover_color=None, text_color=None):
|
||||||
if bg_color is not None:
|
if bg_color is not None:
|
||||||
|
@ -27,11 +27,11 @@ class CTkColorManager:
|
|||||||
return color
|
return color
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def rgb2hex(rgb_color: tuple):
|
def rgb2hex(rgb_color: tuple) -> str:
|
||||||
return "#{:02x}{:02x}{:02x}".format(round(rgb_color[0]), round(rgb_color[1]), round(rgb_color[2]))
|
return "#{:02x}{:02x}{:02x}".format(round(rgb_color[0]), round(rgb_color[1]), round(rgb_color[2]))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hex2rgb(hex_color: str):
|
def hex2rgb(hex_color: str) -> tuple:
|
||||||
return tuple(int(hex_color.strip("#")[i:i+2], 16) for i in (0, 2, 4))
|
return tuple(int(hex_color.strip("#")[i:i+2], 16) for i in (0, 2, 4))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -117,20 +117,20 @@ class App(tkinter.Tk):
|
|||||||
self.slider_1 = customtkinter.CTkSlider(master=self.frame_right,
|
self.slider_1 = customtkinter.CTkSlider(master=self.frame_right,
|
||||||
button_color=App.MAIN_COLOR,
|
button_color=App.MAIN_COLOR,
|
||||||
button_hover_color=App.MAIN_HOVER,
|
button_hover_color=App.MAIN_HOVER,
|
||||||
width=160,
|
width=160,
|
||||||
height=16,
|
height=16,
|
||||||
border_width=5.5,
|
border_width=5.5,
|
||||||
command=self.progressbar.set)
|
command=self.progressbar.set)
|
||||||
self.slider_1.place(x=20, rely=0.6, anchor=tkinter.W)
|
self.slider_1.place(x=20, rely=0.6, anchor=tkinter.W)
|
||||||
self.slider_1.set(0.3)
|
self.slider_1.set(0.3)
|
||||||
|
|
||||||
self.slider_2 = customtkinter.CTkSlider(master=self.frame_right,
|
self.slider_2 = customtkinter.CTkSlider(master=self.frame_right,
|
||||||
button_color=App.MAIN_COLOR,
|
button_color=App.MAIN_COLOR,
|
||||||
button_hover_color=App.MAIN_HOVER,
|
button_hover_color=App.MAIN_HOVER,
|
||||||
width=160,
|
width=160,
|
||||||
height=16,
|
height=16,
|
||||||
border_width=5.5,
|
border_width=5.5,
|
||||||
command=self.progressbar.set)
|
command=self.progressbar.set)
|
||||||
self.slider_2.place(x=20, rely=0.7, anchor=tkinter.W)
|
self.slider_2.place(x=20, rely=0.7, anchor=tkinter.W)
|
||||||
self.slider_2.set(0.7)
|
self.slider_2.set(0.7)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ customtkinter.enable_macos_darkmode()
|
|||||||
customtkinter.set_appearance_mode("System") # Other: "Dark", "Light"
|
customtkinter.set_appearance_mode("System") # Other: "Dark", "Light"
|
||||||
|
|
||||||
root_tk = tkinter.Tk() # create the Tk window like you normally do
|
root_tk = tkinter.Tk() # create the Tk window like you normally do
|
||||||
root_tk.geometry("400x240")
|
root_tk.geometry("400x400")
|
||||||
root_tk.title("CustomTkinter Test")
|
root_tk.title("CustomTkinter Test")
|
||||||
|
|
||||||
|
|
||||||
@ -21,18 +21,28 @@ def button_function():
|
|||||||
settings_image = ImageTk.PhotoImage(Image.open(PATH + "/test_images/settings.png").resize((40, 40)))
|
settings_image = ImageTk.PhotoImage(Image.open(PATH + "/test_images/settings.png").resize((40, 40)))
|
||||||
bell_image = ImageTk.PhotoImage(Image.open(PATH + "/test_images/bell.png").resize((40, 40)))
|
bell_image = ImageTk.PhotoImage(Image.open(PATH + "/test_images/bell.png").resize((40, 40)))
|
||||||
|
|
||||||
frame_1 = customtkinter.CTkFrame(master=root_tk, width=300, height=200, corner_radius=15)
|
frame_1 = customtkinter.CTkFrame(master=root_tk, width=300, height=350, corner_radius=15)
|
||||||
frame_1.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)
|
frame_1.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)
|
||||||
|
|
||||||
# button with settings-image
|
# button with settings-image and no text
|
||||||
button_1 = customtkinter.CTkButton(master=frame_1, image=settings_image, width=60, height=60,
|
button_1 = customtkinter.CTkButton(master=frame_1, image=settings_image, text="", width=60, height=60,
|
||||||
corner_radius=10, command=button_function)
|
corner_radius=10, command=button_function)
|
||||||
button_1.place(relx=0.33, rely=0.5, anchor=tkinter.CENTER)
|
button_1.place(relx=0.1, rely=0.2, anchor=tkinter.W)
|
||||||
|
|
||||||
# button with bell-image
|
# button with bell-image and standard compound ("left")
|
||||||
button_2 = customtkinter.CTkButton(master=frame_1, image=bell_image, width=60, height=60,
|
button_2 = customtkinter.CTkButton(master=frame_1, image=bell_image, width=60, height=60,
|
||||||
corner_radius=10, command=button_function)
|
corner_radius=10, command=button_function)
|
||||||
button_2.place(relx=0.66, rely=0.5, anchor=tkinter.CENTER)
|
button_2.place(relx=0.9, rely=0.2, anchor=tkinter.E)
|
||||||
|
|
||||||
|
# button with bell-image and compound="bottom"
|
||||||
|
button_4 = customtkinter.CTkButton(master=frame_1, image=bell_image, text="bell_image", compound="bottom",
|
||||||
|
command=button_function, height=100)
|
||||||
|
button_4.place(relx=0.5, rely=0.55, relwidth=0.5, anchor=tkinter.CENTER)
|
||||||
|
|
||||||
|
# button with settings-image and compound="right"
|
||||||
|
button_4 = customtkinter.CTkButton(master=frame_1, image=settings_image, text="bell_image", compound="right",
|
||||||
|
command=button_function, height=60)
|
||||||
|
button_4.place(relx=0.5, rely=0.85, relwidth=0.5, anchor=tkinter.CENTER)
|
||||||
|
|
||||||
root_tk.mainloop()
|
root_tk.mainloop()
|
||||||
customtkinter.disable_macos_darkmode()
|
customtkinter.disable_macos_darkmode()
|
||||||
|
Loading…
Reference in New Issue
Block a user