mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
moved base functionality of widgets to widget_base_class.py
This commit is contained in:
parent
5ede252b2f
commit
992d0cbff0
@ -1,18 +1,18 @@
|
||||
__version__ = "3.12"
|
||||
|
||||
from .widgets.customtkinter_input_dialog import CTkInputDialog
|
||||
from .widgets.customtkinter_button import CTkButton
|
||||
from .widgets.customtkinter_slider import CTkSlider
|
||||
from .widgets.customtkinter_frame import CTkFrame
|
||||
from .widgets.customtkinter_progressbar import CTkProgressBar
|
||||
from .widgets.customtkinter_label import CTkLabel
|
||||
from .widgets.customtkinter_entry import CTkEntry
|
||||
from .widgets.customtkinter_checkbox import CTkCheckBox
|
||||
from .widgets.customtkinter_radiobutton import CTkRadioButton
|
||||
from .widgets.customtkinter_tk import CTk
|
||||
from .widgets.customtkinter_canvas import CTkCanvas
|
||||
from .widgets.customtkinter_switch import CTkSwitch
|
||||
from .widgets.customtkinter_toplevel import CTkToplevel
|
||||
from .widgets.ctk_input_dialog import CTkInputDialog
|
||||
from .widgets.ctk_button import CTkButton
|
||||
from .widgets.ctk_slider import CTkSlider
|
||||
from .widgets.ctk_frame import CTkFrame
|
||||
from .widgets.ctk_progressbar import CTkProgressBar
|
||||
from .widgets.ctk_label import CTkLabel
|
||||
from .widgets.ctk_entry import CTkEntry
|
||||
from .widgets.ctk_checkbox import CTkCheckBox
|
||||
from .widgets.ctk_radiobutton import CTkRadioButton
|
||||
from .widgets.ctk_tk import CTk
|
||||
from .widgets.ctk_canvas import CTkCanvas
|
||||
from .widgets.ctk_switch import CTkSwitch
|
||||
from .widgets.ctk_toplevel import CTkToplevel
|
||||
|
||||
from .customtkinter_settings import CTkSettings
|
||||
from .appearance_mode_tracker import AppearanceModeTracker
|
||||
|
@ -2,7 +2,7 @@ import sys
|
||||
import tkinter
|
||||
from typing import Union
|
||||
|
||||
from .widgets.customtkinter_canvas import CTkCanvas
|
||||
from .widgets.ctk_canvas import CTkCanvas
|
||||
|
||||
|
||||
class CTkDrawEngine:
|
||||
|
@ -1,17 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import sys
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from customtkinter.appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkButton(tkinter.Frame):
|
||||
class CTkButton(CTkBaseClass):
|
||||
""" tkinter custom button with border, rounded corners and hover effect """
|
||||
|
||||
def __init__(self, *args,
|
||||
@ -34,45 +31,18 @@ class CTkButton(tkinter.Frame):
|
||||
compound=tkinter.LEFT,
|
||||
state=tkinter.NORMAL,
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribute>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
self.configure_basic_grid()
|
||||
|
||||
# color variables
|
||||
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color
|
||||
self.hover_color = CTkThemeManager.theme["color"]["button_hover"] if hover_color == "default_theme" else hover_color
|
||||
self.border_color = CTkThemeManager.theme["color"]["button_border"] if border_color == "default_theme" else border_color
|
||||
|
||||
# shape and size
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.configure(width=self.width, height=self.height)
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["button_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["button_border_width"] if border_width == "default_theme" else border_width
|
||||
|
||||
@ -98,7 +68,6 @@ class CTkButton(tkinter.Frame):
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="nsew")
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
# event bindings
|
||||
@ -113,45 +82,13 @@ class CTkButton(tkinter.Frame):
|
||||
self.set_cursor()
|
||||
self.draw() # initial draw
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.set_appearance_mode)
|
||||
super().destroy()
|
||||
|
||||
def configure_basic_grid(self):
|
||||
# Configuration of a basic grid (2x2) in which all elements of CTkButtons are centered on one row and one column
|
||||
# Configuration of a grid system (2x2) in which all parts of CTkButton are centered on one row and one column
|
||||
self.grid_rowconfigure(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):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
self.width = event.width
|
||||
self.height = event.height
|
||||
|
||||
# self.canvas.config(width=self.width, height=self.height)
|
||||
self.draw(no_color_updates=True) # fast drawing without color changes
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def draw(self, no_color_updates=False):
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width)
|
||||
|
||||
@ -256,9 +193,6 @@ class CTkButton(tkinter.Frame):
|
||||
self.image_label.grid(row=1, column=0, padx=max(self.corner_radius, self.border_width), sticky="n", columnspan=2, rowspan=1, pady=(2, self.border_width))
|
||||
self.text_label.grid(row=0, column=0, padx=max(self.corner_radius, self.border_width), sticky="s", columnspan=2, rowspan=1, pady=(self.border_width, 2))
|
||||
|
||||
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
|
||||
|
||||
@ -401,16 +335,3 @@ class CTkButton(tkinter.Frame):
|
||||
self.after(100, self.click_animation)
|
||||
|
||||
self.function()
|
||||
|
||||
def set_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, (CTkFrame, CTk)):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -1,17 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import sys
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkCheckBox(tkinter.Frame):
|
||||
class CTkCheckBox(CTkBaseClass):
|
||||
""" tkinter custom checkbox with border, rounded corners and hover effect """
|
||||
|
||||
def __init__(self, *args,
|
||||
@ -36,59 +33,28 @@ class CTkCheckBox(tkinter.Frame):
|
||||
variable=None,
|
||||
textvariable=None,
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
||||
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
|
||||
# color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color
|
||||
self.hover_color = CTkThemeManager.theme["color"]["button_hover"] if hover_color == "default_theme" else hover_color
|
||||
self.border_color = CTkThemeManager.theme["color"]["checkbox_border"] if border_color == "default_theme" else border_color
|
||||
self.checkmark_color = CTkThemeManager.theme["color"]["checkmark"] if checkmark_color == "default_theme" else checkmark_color
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["checkbox_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["checkbox_border_width"] if border_width == "default_theme" else border_width
|
||||
|
||||
if self.corner_radius*2 > self.height:
|
||||
self.corner_radius = self.height/2
|
||||
elif self.corner_radius*2 > self.width:
|
||||
self.corner_radius = self.width/2
|
||||
|
||||
if self.corner_radius >= self.border_width:
|
||||
self.inner_corner_radius = self.corner_radius - self.border_width
|
||||
else:
|
||||
self.inner_corner_radius = 0
|
||||
|
||||
# text
|
||||
self.text = text
|
||||
self.text_label = None
|
||||
self.text_color = CTkThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||
self.text_color_disabled = CTkThemeManager.theme["color"]["text_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
|
||||
self.text_font = (CTkThemeManager.theme["text"]["font"], CTkThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
|
||||
|
||||
# callback and hover functionality
|
||||
self.function = command
|
||||
self.state = state
|
||||
self.hover = hover
|
||||
@ -100,7 +66,7 @@ class CTkCheckBox(tkinter.Frame):
|
||||
self.textvariable = textvariable
|
||||
self.variable_callback_name = None
|
||||
|
||||
# configure grid system
|
||||
# configure grid system (1x3)
|
||||
self.grid_columnconfigure(0, weight=0)
|
||||
self.grid_columnconfigure(1, weight=0, minsize=6)
|
||||
self.grid_columnconfigure(2, weight=1)
|
||||
@ -110,7 +76,6 @@ class CTkCheckBox(tkinter.Frame):
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1)
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
if self.hover is True:
|
||||
@ -120,11 +85,7 @@ class CTkCheckBox(tkinter.Frame):
|
||||
self.canvas.bind("<Button-1>", self.toggle)
|
||||
self.canvas.bind("<Button-1>", self.toggle)
|
||||
|
||||
self.text_label = None
|
||||
|
||||
self.set_cursor()
|
||||
self.draw() # initial draw
|
||||
|
||||
# set select state according to variable
|
||||
if self.variable is not None:
|
||||
self.variable_callback_name = self.variable.trace_add("write", self.variable_callback)
|
||||
if self.variable.get() == self.onvalue:
|
||||
@ -132,34 +93,16 @@ class CTkCheckBox(tkinter.Frame):
|
||||
elif self.variable.get() == self.offvalue:
|
||||
self.deselect(from_variable_callback=True)
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.set_appearance_mode)
|
||||
self.set_cursor()
|
||||
self.draw() # initial draw
|
||||
|
||||
def destroy(self):
|
||||
if self.variable is not None:
|
||||
self.variable.trace_remove("write", self.variable_callback_name)
|
||||
|
||||
super().destroy()
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def draw(self):
|
||||
def draw(self, no_color_updates=False):
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width)
|
||||
|
||||
if self.check_state is True:
|
||||
@ -207,9 +150,6 @@ class CTkCheckBox(tkinter.Frame):
|
||||
|
||||
self.set_text(self.text)
|
||||
|
||||
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()
|
||||
|
||||
@ -378,16 +318,3 @@ class CTkCheckBox(tkinter.Frame):
|
||||
|
||||
def get(self):
|
||||
return self.onvalue if self.check_state is True else self.offvalue
|
||||
|
||||
def set_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, (CTkFrame, CTk)):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -1,18 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkEntry(tkinter.Frame):
|
||||
class CTkEntry(CTkBaseClass):
|
||||
def __init__(self, *args,
|
||||
master=None,
|
||||
bg_color=None,
|
||||
fg_color="default_theme",
|
||||
text_color="default_theme",
|
||||
@ -25,39 +21,16 @@ class CTkEntry(tkinter.Frame):
|
||||
width=120,
|
||||
height=30,
|
||||
**kwargs):
|
||||
if master is None:
|
||||
super().__init__(*args)
|
||||
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
if "master" in kwargs:
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, master=kwargs["master"])
|
||||
del kwargs["master"]
|
||||
else:
|
||||
super().__init__(*args, master=master)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.change_appearance_mode, self)
|
||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height)
|
||||
|
||||
self.configure_basic_grid()
|
||||
|
||||
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["entry"] if fg_color == "default_theme" else fg_color
|
||||
self.text_color = CTkThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||
self.placeholder_text_color = CTkThemeManager.theme["color"]["entry_placeholder_text"] if placeholder_text_color == "default_theme" else placeholder_text_color
|
||||
@ -68,23 +41,15 @@ class CTkEntry(tkinter.Frame):
|
||||
self.placeholder_text_active = False
|
||||
self.pre_placeholder_arguments = {} # some set arguments of the entry will be changed for placeholder and then set back
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["button_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["entry_border_width"] if border_width == "default_theme" else border_width
|
||||
|
||||
if self.corner_radius*2 > self.height:
|
||||
self.corner_radius = self.height/2
|
||||
elif self.corner_radius*2 > self.width:
|
||||
self.corner_radius = self.width/2
|
||||
|
||||
super().configure(width=self.width, height=self.height)
|
||||
|
||||
self.canvas = CTkCanvas(master=self,
|
||||
highlightthickness=0,
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(column=0, row=0, sticky="we")
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
self.entry = tkinter.Entry(master=self,
|
||||
bd=0,
|
||||
@ -94,8 +59,6 @@ class CTkEntry(tkinter.Frame):
|
||||
**kwargs)
|
||||
self.entry.grid(column=0, row=0, sticky="we", padx=self.corner_radius if self.corner_radius >= 6 else 6)
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
super().bind('<Configure>', self.update_dimensions)
|
||||
self.entry.bind('<FocusOut>', self.set_placeholder)
|
||||
self.entry.bind('<FocusIn>', self.clear_placeholder)
|
||||
@ -103,42 +66,10 @@ class CTkEntry(tkinter.Frame):
|
||||
self.draw()
|
||||
self.set_placeholder()
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.change_appearance_mode)
|
||||
super().destroy()
|
||||
|
||||
def configure_basic_grid(self):
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def update_dimensions(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
# print(event.x, event.width, self.width)
|
||||
self.width = event.width
|
||||
self.height = event.height
|
||||
|
||||
self.draw()
|
||||
|
||||
def set_placeholder(self, event=None):
|
||||
if self.placeholder_text is not None:
|
||||
if not self.placeholder_text_active and self.entry.get() == "":
|
||||
@ -156,7 +87,7 @@ class CTkEntry(tkinter.Frame):
|
||||
for argument, value in self.pre_placeholder_arguments.items():
|
||||
self.entry[argument] = value
|
||||
|
||||
def draw(self):
|
||||
def draw(self, no_color_updates=False):
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width)
|
||||
@ -188,16 +119,16 @@ class CTkEntry(tkinter.Frame):
|
||||
def bind(self, *args, **kwargs):
|
||||
self.entry.bind(*args, **kwargs)
|
||||
|
||||
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 "bg_color" in kwargs:
|
||||
self.bg_color = kwargs["bg_color"]
|
||||
del kwargs["bg_color"]
|
||||
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 "fg_color" in kwargs:
|
||||
self.fg_color = kwargs["fg_color"]
|
||||
@ -232,7 +163,6 @@ class CTkEntry(tkinter.Frame):
|
||||
def delete(self, *args, **kwargs):
|
||||
self.entry.delete(*args, **kwargs)
|
||||
self.set_placeholder()
|
||||
return
|
||||
|
||||
def insert(self, *args, **kwargs):
|
||||
self.clear_placeholder()
|
||||
@ -243,16 +173,3 @@ class CTkEntry(tkinter.Frame):
|
||||
return ""
|
||||
else:
|
||||
return self.entry.get()
|
||||
|
||||
def change_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, (CTkFrame, CTk)):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
111
customtkinter/widgets/ctk_frame.py
Normal file
111
customtkinter/widgets/ctk_frame.py
Normal file
@ -0,0 +1,111 @@
|
||||
import tkinter
|
||||
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkFrame(CTkBaseClass):
|
||||
def __init__(self, *args,
|
||||
bg_color=None,
|
||||
fg_color="default_theme",
|
||||
border_color="default_theme",
|
||||
border_width="default_theme",
|
||||
corner_radius="default_theme",
|
||||
width=200,
|
||||
height=200,
|
||||
**kwargs):
|
||||
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
# color
|
||||
self.border_color = CTkThemeManager.theme["color"]["frame_border"] if border_color == "default_theme" else border_color
|
||||
|
||||
if fg_color == "default_theme":
|
||||
if isinstance(self.master, CTkFrame):
|
||||
if self.master.fg_color == CTkThemeManager.theme["color"]["frame_low"]:
|
||||
self.fg_color = CTkThemeManager.theme["color"]["frame_high"]
|
||||
else:
|
||||
self.fg_color = CTkThemeManager.theme["color"]["frame_low"]
|
||||
else:
|
||||
self.fg_color = CTkThemeManager.theme["color"]["frame_low"]
|
||||
else:
|
||||
self.fg_color = fg_color
|
||||
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["frame_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["frame_border_width"] if border_width == "default_theme" else border_width
|
||||
|
||||
self.canvas = CTkCanvas(master=self,
|
||||
highlightthickness=0,
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.place(x=0, y=0, relwidth=1, relheight=1)
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
self.bind('<Configure>', self.update_dimensions)
|
||||
|
||||
self.draw()
|
||||
|
||||
def winfo_children(self):
|
||||
""" winfo_children of CTkFrame without self.canvas widget,
|
||||
because it's not a child but part of the CTkFrame itself """
|
||||
|
||||
child_widgets = super().winfo_children()
|
||||
try:
|
||||
child_widgets.remove(self.canvas)
|
||||
return child_widgets
|
||||
except ValueError:
|
||||
return child_widgets
|
||||
|
||||
def draw(self, no_color_updates=False):
|
||||
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width)
|
||||
|
||||
if no_color_updates is False or requires_recoloring:
|
||||
self.canvas.itemconfig("inner_parts",
|
||||
fill=CTkThemeManager.single_color(self.fg_color, self.appearance_mode),
|
||||
outline=CTkThemeManager.single_color(self.fg_color, self.appearance_mode))
|
||||
self.canvas.itemconfig("border_parts",
|
||||
fill=CTkThemeManager.single_color(self.border_color, self.appearance_mode),
|
||||
outline=CTkThemeManager.single_color(self.border_color, self.appearance_mode))
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
self.canvas.tag_lower("inner_parts")
|
||||
self.canvas.tag_lower("border_parts")
|
||||
|
||||
def configure(self, *args, **kwargs):
|
||||
require_redraw = False # some attribute changes require a call of self.draw() at the end
|
||||
|
||||
if "fg_color" in kwargs:
|
||||
self.fg_color = kwargs["fg_color"]
|
||||
require_redraw = True
|
||||
del kwargs["fg_color"]
|
||||
|
||||
# check if CTk widgets are children of the frame and change their bg_color to new frame fg_color
|
||||
for child in self.winfo_children():
|
||||
if isinstance(child, CTkBaseClass):
|
||||
child.configure(bg_color=self.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 "corner_radius" in kwargs:
|
||||
self.corner_radius = kwargs["corner_radius"]
|
||||
require_redraw = True
|
||||
del kwargs["corner_radius"]
|
||||
|
||||
super().configure(*args, **kwargs)
|
||||
|
||||
if require_redraw:
|
||||
self.draw()
|
@ -1,11 +1,11 @@
|
||||
import tkinter
|
||||
import time
|
||||
|
||||
from .customtkinter_label import CTkLabel
|
||||
from .customtkinter_entry import CTkEntry
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_toplevel import CTkToplevel
|
||||
from .customtkinter_button import CTkButton
|
||||
from .ctk_label import CTkLabel
|
||||
from .ctk_entry import CTkEntry
|
||||
from .ctk_frame import CTkFrame
|
||||
from .ctk_toplevel import CTkToplevel
|
||||
from .ctk_button import CTkButton
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
|
@ -1,18 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkLabel(tkinter.Frame):
|
||||
class CTkLabel(CTkBaseClass):
|
||||
def __init__(self, *args,
|
||||
master=None,
|
||||
bg_color=None,
|
||||
fg_color="default_theme",
|
||||
text_color="default_theme",
|
||||
@ -22,54 +18,28 @@ class CTkLabel(tkinter.Frame):
|
||||
text="CTkLabel",
|
||||
text_font="default_theme",
|
||||
**kwargs):
|
||||
if master is None:
|
||||
super().__init__(*args)
|
||||
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
if "master" in kwargs:
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, master=kwargs["master"])
|
||||
del kwargs["master"]
|
||||
else:
|
||||
super().__init__(*args, master=master)
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.change_appearance_mode, self)
|
||||
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
|
||||
# color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["label"] if fg_color == "default_theme" else fg_color
|
||||
if self.fg_color is None:
|
||||
self.fg_color = self.bg_color
|
||||
self.text_color = CTkThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["label_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
|
||||
if self.corner_radius * 2 > self.height:
|
||||
self.corner_radius = self.height / 2
|
||||
elif self.corner_radius * 2 > self.width:
|
||||
self.corner_radius = self.width / 2
|
||||
|
||||
# text
|
||||
self.text = text
|
||||
self.text_font = (CTkThemeManager.theme["text"]["font"], CTkThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
|
||||
|
||||
# configure grid system (1x1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
|
||||
@ -78,6 +48,7 @@ class CTkLabel(tkinter.Frame):
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(row=0, column=0, sticky="nswe")
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
self.text_label = tkinter.Label(master=self,
|
||||
highlightthickness=0,
|
||||
@ -87,46 +58,10 @@ class CTkLabel(tkinter.Frame):
|
||||
**kwargs)
|
||||
self.text_label.grid(row=0, column=0, padx=self.corner_radius)
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
super().configure(width=self.width, height=self.height)
|
||||
|
||||
self.bind('<Configure>', self.update_dimensions)
|
||||
self.draw()
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.change_appearance_mode)
|
||||
super().destroy()
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def update_dimensions(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
self.width = event.width
|
||||
self.height = event.height
|
||||
|
||||
# self.canvas.config(width=self.width, height=self.height)
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self, no_color_updates=False):
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, 0)
|
||||
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
@ -146,9 +81,6 @@ class CTkLabel(tkinter.Frame):
|
||||
self.text_label.configure(fg=CTkThemeManager.single_color(self.text_color, self.appearance_mode),
|
||||
bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
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
|
||||
|
||||
@ -182,16 +114,3 @@ class CTkLabel(tkinter.Frame):
|
||||
def set_text(self, text):
|
||||
self.text = text
|
||||
self.text_label.configure(text=self.text, width=len(self.text))
|
||||
|
||||
def change_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, (CTkFrame, CTk)):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -1,17 +1,13 @@
|
||||
import sys
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkProgressBar(tkinter.Frame):
|
||||
class CTkProgressBar(CTkBaseClass):
|
||||
""" tkinter custom progressbar, always horizontal, values are from 0 to 1 """
|
||||
|
||||
def __init__(self, *args,
|
||||
@ -25,56 +21,30 @@ class CTkProgressBar(tkinter.Frame):
|
||||
height=8,
|
||||
border_width="default_theme",
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.change_appearance_mode, self)
|
||||
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
|
||||
# color
|
||||
self.border_color = CTkThemeManager.theme["color"]["progressbar_border"] if border_color == "default_theme" else border_color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["progressbar"] if fg_color == "default_theme" else fg_color
|
||||
self.progress_color = CTkThemeManager.theme["color"]["progressbar_progress"] if progress_color == "default_theme" else progress_color
|
||||
|
||||
# control variable
|
||||
self.variable = variable
|
||||
self.variable_callback_blocked = False
|
||||
self.variable_callback_name = None
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["progressbar_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["progressbar_border_width"] if border_width == "default_theme" else border_width
|
||||
self.value = 0.5
|
||||
|
||||
self.configure(width=self.width, height=self.height)
|
||||
|
||||
self.canvas = CTkCanvas(master=self,
|
||||
highlightthickness=0,
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.place(x=0, y=0, relwidth=1, relheight=1)
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
# Each time an item is resized due to pack position mode, the binding Configure is called on the widget
|
||||
@ -89,53 +59,11 @@ class CTkProgressBar(tkinter.Frame):
|
||||
self.variable_callback_blocked = False
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.change_appearance_mode)
|
||||
|
||||
if self.variable is not None:
|
||||
self.variable.trace_remove("write", self.variable_callback_name)
|
||||
|
||||
super().destroy()
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
@staticmethod
|
||||
def calc_optimal_height(user_height):
|
||||
if sys.platform == "darwin":
|
||||
return user_height # on macOS just use given value (canvas has Antialiasing)
|
||||
else:
|
||||
# make sure the value is always with uneven for better rendering of the ovals
|
||||
if user_height == 0:
|
||||
return 0
|
||||
elif user_height % 2 == 0:
|
||||
return user_height + 1
|
||||
else:
|
||||
return user_height
|
||||
|
||||
def update_dimensions(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
self.width = event.width
|
||||
self.height = event.height
|
||||
|
||||
self.draw()
|
||||
|
||||
def draw(self, no_color_updates=False):
|
||||
|
||||
requires_recoloring = self.draw_engine.draw_rounded_progress_bar_with_border(self.width, self.height, self.corner_radius, self.border_width, self.value, "w")
|
||||
@ -156,9 +84,12 @@ class CTkProgressBar(tkinter.Frame):
|
||||
require_redraw = False # some attribute changes require a call of self.draw() at the end
|
||||
|
||||
if "bg_color" in kwargs:
|
||||
self.bg_color = kwargs["bg_color"]
|
||||
del kwargs["bg_color"]
|
||||
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 "fg_color" in kwargs:
|
||||
self.fg_color = kwargs["fg_color"]
|
||||
@ -217,16 +148,3 @@ class CTkProgressBar(tkinter.Frame):
|
||||
self.variable_callback_blocked = True
|
||||
self.variable.set(round(self.value) if isinstance(self.variable, tkinter.IntVar) else self.value)
|
||||
self.variable_callback_blocked = False
|
||||
|
||||
def change_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, CTkFrame):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -1,17 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import sys
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkRadioButton(tkinter.Frame):
|
||||
class CTkRadioButton(CTkBaseClass):
|
||||
def __init__(self, *args,
|
||||
bg_color=None,
|
||||
fg_color="default_theme",
|
||||
@ -33,60 +30,29 @@ class CTkRadioButton(tkinter.Frame):
|
||||
variable=None,
|
||||
textvariable=None,
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
||||
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
|
||||
# color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color
|
||||
self.hover_color = CTkThemeManager.theme["color"]["button_hover"] if hover_color == "default_theme" else hover_color
|
||||
self.border_color = CTkThemeManager.theme["color"]["checkbox_border"] if border_color == "default_theme" else border_color
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["radiobutton_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width_unchecked = CTkThemeManager.theme["shape"]["radiobutton_border_width_unchecked"] if border_width_unchecked == "default_theme" else border_width_unchecked
|
||||
self.border_width_checked = CTkThemeManager.theme["shape"]["radiobutton_border_width_checked"] if border_width_checked == "default_theme" else border_width_checked
|
||||
self.border_width = self.border_width_unchecked
|
||||
|
||||
if self.corner_radius*2 > self.height:
|
||||
self.corner_radius = self.height/2
|
||||
elif self.corner_radius*2 > self.width:
|
||||
self.corner_radius = self.width/2
|
||||
|
||||
if self.corner_radius >= self.border_width:
|
||||
self.inner_corner_radius = self.corner_radius - self.border_width
|
||||
else:
|
||||
self.inner_corner_radius = 0
|
||||
|
||||
# text
|
||||
self.text = text
|
||||
self.text_label = None
|
||||
self.text_color = CTkThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||
self.text_color_disabled = CTkThemeManager.theme["color"]["text_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
|
||||
self.text_font = (CTkThemeManager.theme["text"]["font"], CTkThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
|
||||
|
||||
# callback and control variables
|
||||
self.function = command
|
||||
self.state = state
|
||||
self.hover = hover
|
||||
@ -97,7 +63,7 @@ class CTkRadioButton(tkinter.Frame):
|
||||
self.textvariable = textvariable
|
||||
self.variable_callback_name = None
|
||||
|
||||
# configure grid system
|
||||
# configure grid system (3x1)
|
||||
self.grid_columnconfigure(0, weight=0)
|
||||
self.grid_columnconfigure(1, weight=0, minsize=6)
|
||||
self.grid_columnconfigure(2, weight=1)
|
||||
@ -107,7 +73,6 @@ class CTkRadioButton(tkinter.Frame):
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1)
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
self.canvas.bind("<Enter>", self.on_enter)
|
||||
@ -115,8 +80,6 @@ class CTkRadioButton(tkinter.Frame):
|
||||
self.canvas.bind("<Button-1>", self.invoke)
|
||||
self.canvas.bind("<Button-1>", self.invoke)
|
||||
|
||||
self.text_label = None
|
||||
|
||||
self.set_cursor()
|
||||
self.draw() # initial draw
|
||||
|
||||
@ -128,33 +91,12 @@ class CTkRadioButton(tkinter.Frame):
|
||||
self.deselect(from_variable_callback=True)
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.set_appearance_mode)
|
||||
|
||||
if self.variable is not None:
|
||||
self.variable.trace_remove("write", self.variable_callback_name)
|
||||
|
||||
super().destroy()
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def draw(self):
|
||||
def draw(self, no_color_updates=False):
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width)
|
||||
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
@ -191,9 +133,6 @@ class CTkRadioButton(tkinter.Frame):
|
||||
|
||||
self.set_text(self.text)
|
||||
|
||||
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()
|
||||
|
||||
@ -338,16 +277,3 @@ class CTkRadioButton(tkinter.Frame):
|
||||
self.variable_callback_blocked = True
|
||||
self.variable.set("")
|
||||
self.variable_callback_blocked = False
|
||||
|
||||
def set_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, (CTkFrame, CTk)):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -1,17 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import sys
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkSlider(tkinter.Frame):
|
||||
class CTkSlider(CTkBaseClass):
|
||||
""" tkinter custom slider, always horizontal """
|
||||
|
||||
def __init__(self, *args,
|
||||
@ -33,44 +30,18 @@ class CTkSlider(tkinter.Frame):
|
||||
command=None,
|
||||
variable=None,
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.change_appearance_mode, self)
|
||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||
|
||||
self.configure_basic_grid()
|
||||
|
||||
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
|
||||
# color
|
||||
self.border_color = border_color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["slider"] if fg_color == "default_theme" else fg_color
|
||||
self.progress_color = CTkThemeManager.theme["color"]["slider_progress"] if progress_color == "default_theme" else progress_color
|
||||
self.button_color = CTkThemeManager.theme["color"]["slider_button"] if button_color == "default_theme" else button_color
|
||||
self.button_hover_color = CTkThemeManager.theme["color"]["slider_button_hover"] if button_hover_color == "default_theme" else button_hover_color
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["slider_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.button_corner_radius = CTkThemeManager.theme["shape"]["slider_button_corner_radius"] if button_corner_radius == "default_theme" else button_corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["slider_border_width"] if border_width == "default_theme" else border_width
|
||||
@ -85,23 +56,17 @@ class CTkSlider(tkinter.Frame):
|
||||
if self.corner_radius < self.button_corner_radius:
|
||||
self.corner_radius = self.button_corner_radius
|
||||
|
||||
# callback and control variables
|
||||
self.callback_function = command
|
||||
self.variable: tkinter.Variable = variable
|
||||
self.variable_callback_blocked = False
|
||||
self.variable_callback_name = None
|
||||
|
||||
self.configure(width=self.width, height=self.height)
|
||||
if sys.platform == "darwin":
|
||||
self.configure(cursor="pointinghand")
|
||||
elif sys.platform.startswith("win"):
|
||||
self.configure(cursor="hand2")
|
||||
|
||||
self.canvas = CTkCanvas(master=self,
|
||||
highlightthickness=0,
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(column=0, row=0, sticky="nswe")
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
self.canvas.bind("<Enter>", self.on_enter)
|
||||
@ -112,6 +77,7 @@ class CTkSlider(tkinter.Frame):
|
||||
# Each time an item is resized due to pack position mode, the binding Configure is called on the widget
|
||||
self.bind('<Configure>', self.update_dimensions)
|
||||
|
||||
self.set_cursor()
|
||||
self.draw() # initial draw
|
||||
|
||||
if self.variable is not None:
|
||||
@ -121,9 +87,6 @@ class CTkSlider(tkinter.Frame):
|
||||
self.variable_callback_blocked = False
|
||||
|
||||
def destroy(self):
|
||||
# remove change_appearance_mode function from callback list of AppearanceModeTracker
|
||||
AppearanceModeTracker.remove(self.change_appearance_mode)
|
||||
|
||||
# remove variable_callback from variable callbacks if variable exists
|
||||
if self.variable is not None:
|
||||
self.variable.trace_remove("write", self.variable_callback_name)
|
||||
@ -134,52 +97,17 @@ class CTkSlider(tkinter.Frame):
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
@staticmethod
|
||||
def calc_optimal_height(user_height):
|
||||
def set_cursor(self):
|
||||
if sys.platform == "darwin":
|
||||
return user_height # on macOS just use given value (canvas has Antialiasing)
|
||||
else:
|
||||
# make sure the value is always with uneven for better rendering of the ovals
|
||||
if user_height == 0:
|
||||
return 0
|
||||
elif user_height % 2 == 0:
|
||||
return user_height + 1
|
||||
else:
|
||||
return user_height
|
||||
|
||||
def update_dimensions(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
self.width = event.width
|
||||
self.height = event.height
|
||||
|
||||
self.draw()
|
||||
|
||||
def draw(self, color_updates=True):
|
||||
self.configure(cursor="pointinghand")
|
||||
elif sys.platform.startswith("win"):
|
||||
self.configure(cursor="hand2")
|
||||
|
||||
def draw(self, no_color_updates=False):
|
||||
requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width,
|
||||
self.button_length, self.button_corner_radius, self.value, "w")
|
||||
|
||||
if color_updates or requires_recoloring:
|
||||
if no_color_updates is False or requires_recoloring:
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
if self.border_color is None:
|
||||
@ -213,7 +141,7 @@ class CTkSlider(tkinter.Frame):
|
||||
self.output_value = self.round_to_step_size(self.from_ + (self.value * (self.to - self.from_)))
|
||||
self.value = (self.output_value - self.from_) / (self.to - self.from_)
|
||||
|
||||
self.draw(color_updates=False)
|
||||
self.draw(no_color_updates=False)
|
||||
|
||||
if self.callback_function is not None:
|
||||
self.callback_function(self.output_value)
|
||||
@ -259,7 +187,7 @@ class CTkSlider(tkinter.Frame):
|
||||
self.output_value = self.round_to_step_size(output_value)
|
||||
self.value = (self.output_value - self.from_) / (self.to - self.from_)
|
||||
|
||||
self.draw(color_updates=False)
|
||||
self.draw(no_color_updates=False)
|
||||
|
||||
if self.callback_function is not None:
|
||||
self.callback_function(self.output_value)
|
||||
@ -273,9 +201,6 @@ class CTkSlider(tkinter.Frame):
|
||||
if not self.variable_callback_blocked:
|
||||
self.set(self.variable.get(), from_variable_callback=True)
|
||||
|
||||
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
|
||||
|
||||
@ -354,16 +279,3 @@ class CTkSlider(tkinter.Frame):
|
||||
|
||||
if require_redraw:
|
||||
self.draw()
|
||||
|
||||
def change_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, CTkFrame):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -1,17 +1,14 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import sys
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from .ctk_canvas import CTkCanvas
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
from .widget_base_class import CTkBaseClass
|
||||
|
||||
|
||||
class CTkSwitch(tkinter.Frame):
|
||||
class CTkSwitch(CTkBaseClass):
|
||||
def __init__(self, *args,
|
||||
text="CTkSwitch",
|
||||
text_font="default_theme",
|
||||
@ -34,34 +31,11 @@ class CTkSwitch(tkinter.Frame):
|
||||
variable=None,
|
||||
textvariable=None,
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
# transfer basic functionality (bg_color, size, appearance_mode, scaling) to CTkBaseClass
|
||||
super().__init__(*args, bg_color=bg_color, width=width, height=height, **kwargs)
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.change_appearance_mode, self)
|
||||
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
|
||||
# color
|
||||
self.border_color = border_color
|
||||
self.fg_color = CTkThemeManager.theme["color"]["switch"] if fg_color == "default_theme" else fg_color
|
||||
self.progress_color = CTkThemeManager.theme["color"]["switch_progress"] if progress_color == "default_theme" else progress_color
|
||||
@ -69,10 +43,12 @@ class CTkSwitch(tkinter.Frame):
|
||||
self.button_hover_color = CTkThemeManager.theme["color"]["switch_button_hover"] if button_hover_color == "default_theme" else button_hover_color
|
||||
self.text_color = CTkThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
|
||||
|
||||
# text
|
||||
self.text = text
|
||||
self.text_label = None
|
||||
self.text_font = (CTkThemeManager.theme["text"]["font"], CTkThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
# shape
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["switch_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
# self.button_corner_radius = CTkThemeManager.theme["shape"]["switch_button_corner_radius"] if button_corner_radius == "default_theme" else button_corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["switch_border_width"] if border_width == "default_theme" else border_width
|
||||
@ -82,16 +58,17 @@ class CTkSwitch(tkinter.Frame):
|
||||
self.onvalue = onvalue
|
||||
self.offvalue = offvalue
|
||||
|
||||
#if self.corner_radius < self.button_corner_radius:
|
||||
# self.corner_radius = self.button_corner_radius
|
||||
# if self.corner_radius < self.button_corner_radius:
|
||||
# self.corner_radius = self.button_corner_radius
|
||||
|
||||
# callback and control variables
|
||||
self.callback_function = command
|
||||
self.variable: tkinter.Variable = variable
|
||||
self.variable_callback_blocked = False
|
||||
self.variable_callback_name = None
|
||||
self.textvariable = textvariable
|
||||
|
||||
# configure grid system
|
||||
# configure grid system (3x1)
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_columnconfigure(1, weight=0, minsize=6)
|
||||
self.grid_columnconfigure(2, weight=0)
|
||||
@ -101,20 +78,13 @@ class CTkSwitch(tkinter.Frame):
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1, sticky="nswe")
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
if sys.platform == "darwin" and CTkSettings.hand_cursor_enabled:
|
||||
self.canvas.configure(cursor="pointinghand")
|
||||
elif sys.platform.startswith("win") and CTkSettings.hand_cursor_enabled:
|
||||
self.canvas.configure(cursor="hand2")
|
||||
|
||||
self.canvas.bind("<Enter>", self.on_enter)
|
||||
self.canvas.bind("<Leave>", self.on_leave)
|
||||
self.canvas.bind("<Button-1>", self.toggle)
|
||||
|
||||
self.text_label = None
|
||||
|
||||
self.set_cursor()
|
||||
self.draw() # initial draw
|
||||
|
||||
if self.variable is not None:
|
||||
@ -125,35 +95,19 @@ class CTkSwitch(tkinter.Frame):
|
||||
self.deselect(from_variable_callback=True)
|
||||
|
||||
def destroy(self):
|
||||
# remove change_appearance_mode function from callback list of AppearanceModeTracker
|
||||
AppearanceModeTracker.remove(self.change_appearance_mode)
|
||||
|
||||
# remove variable_callback from variable callbacks if variable exists
|
||||
if self.variable is not None:
|
||||
self.variable.trace_remove("write", self.variable_callback_name)
|
||||
|
||||
super().destroy()
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
def set_cursor(self):
|
||||
if sys.platform == "darwin" and CTkSettings.hand_cursor_enabled:
|
||||
self.canvas.configure(cursor="pointinghand")
|
||||
elif sys.platform.startswith("win") and CTkSettings.hand_cursor_enabled:
|
||||
self.canvas.configure(cursor="hand2")
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def draw(self, color_updates=True):
|
||||
def draw(self, no_color_updates=False):
|
||||
|
||||
if self.check_state is True:
|
||||
requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width,
|
||||
@ -162,7 +116,7 @@ class CTkSwitch(tkinter.Frame):
|
||||
requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width,
|
||||
self.button_length, self.corner_radius, 0, "w")
|
||||
|
||||
if color_updates or requires_recoloring:
|
||||
if no_color_updates is False or requires_recoloring:
|
||||
self.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
@ -186,8 +140,6 @@ class CTkSwitch(tkinter.Frame):
|
||||
self.canvas.itemconfig("slider_parts", fill=CTkThemeManager.single_color(self.button_color, self.appearance_mode),
|
||||
outline=CTkThemeManager.single_color(self.button_color, self.appearance_mode))
|
||||
|
||||
# self.canvas.configure(bg="red")
|
||||
|
||||
if self.text_label is None:
|
||||
self.text_label = tkinter.Label(master=self,
|
||||
bd=0,
|
||||
@ -208,8 +160,6 @@ class CTkSwitch(tkinter.Frame):
|
||||
self.text = text
|
||||
if self.text_label is not None:
|
||||
self.text_label.configure(text=self.text)
|
||||
else:
|
||||
sys.stderr.write("ERROR (CTkSwitch): Cant change text because checkbox has no text.")
|
||||
|
||||
def toggle(self, event=None):
|
||||
if self.check_state is True:
|
||||
@ -217,7 +167,7 @@ class CTkSwitch(tkinter.Frame):
|
||||
else:
|
||||
self.check_state = True
|
||||
|
||||
self.draw(color_updates=False)
|
||||
self.draw(no_color_updates=True)
|
||||
|
||||
if self.callback_function is not None:
|
||||
self.callback_function()
|
||||
@ -230,7 +180,7 @@ class CTkSwitch(tkinter.Frame):
|
||||
def select(self, from_variable_callback=False):
|
||||
self.check_state = True
|
||||
|
||||
self.draw(color_updates=False)
|
||||
self.draw(no_color_updates=True)
|
||||
|
||||
if self.callback_function is not None:
|
||||
self.callback_function()
|
||||
@ -243,7 +193,7 @@ class CTkSwitch(tkinter.Frame):
|
||||
def deselect(self, from_variable_callback=False):
|
||||
self.check_state = False
|
||||
|
||||
self.draw(color_updates=False)
|
||||
self.draw(no_color_updates=True)
|
||||
|
||||
if self.callback_function is not None:
|
||||
self.callback_function()
|
||||
@ -273,9 +223,6 @@ class CTkSwitch(tkinter.Frame):
|
||||
elif self.variable.get() == self.offvalue:
|
||||
self.deselect(from_variable_callback=True)
|
||||
|
||||
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
|
||||
|
||||
@ -349,16 +296,3 @@ class CTkSwitch(tkinter.Frame):
|
||||
|
||||
if require_redraw:
|
||||
self.draw()
|
||||
|
||||
def change_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, CTkFrame):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
@ -97,13 +97,13 @@ class CTk(tkinter.Tk):
|
||||
args[0]["background"] = CTkThemeManager.single_color(self.fg_color, self.appearance_mode)
|
||||
|
||||
if bg_changed:
|
||||
from .customtkinter_slider import CTkSlider
|
||||
from .customtkinter_progressbar import CTkProgressBar
|
||||
from .customtkinter_label import CTkLabel
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_entry import CTkEntry
|
||||
from customtkinter.widgets.customtkinter_checkbox import CTkCheckBox
|
||||
from customtkinter.widgets.customtkinter_button import CTkButton
|
||||
from .ctk_slider import CTkSlider
|
||||
from .ctk_progressbar import CTkProgressBar
|
||||
from .ctk_label import CTkLabel
|
||||
from .ctk_frame import CTkFrame
|
||||
from .ctk_entry import CTkEntry
|
||||
from customtkinter.widgets.ctk_checkbox import CTkCheckBox
|
||||
from customtkinter.widgets.ctk_button import CTkButton
|
||||
|
||||
for child in self.winfo_children():
|
||||
if isinstance(child, (CTkFrame, CTkButton, CTkLabel, CTkSlider, CTkCheckBox, CTkEntry, CTkProgressBar)):
|
@ -83,13 +83,13 @@ class CTkToplevel(tkinter.Toplevel):
|
||||
args[0]["background"] = CTkThemeManager.single_color(self.fg_color, self.appearance_mode)
|
||||
|
||||
if bg_changed:
|
||||
from .customtkinter_slider import CTkSlider
|
||||
from .customtkinter_progressbar import CTkProgressBar
|
||||
from .customtkinter_label import CTkLabel
|
||||
from .customtkinter_frame import CTkFrame
|
||||
from .customtkinter_entry import CTkEntry
|
||||
from customtkinter.widgets.customtkinter_checkbox import CTkCheckBox
|
||||
from customtkinter.widgets.customtkinter_button import CTkButton
|
||||
from .ctk_slider import CTkSlider
|
||||
from .ctk_progressbar import CTkProgressBar
|
||||
from .ctk_label import CTkLabel
|
||||
from .ctk_frame import CTkFrame
|
||||
from .ctk_entry import CTkEntry
|
||||
from customtkinter.widgets.ctk_checkbox import CTkCheckBox
|
||||
from customtkinter.widgets.ctk_button import CTkButton
|
||||
|
||||
for child in self.winfo_children():
|
||||
if isinstance(child, (CTkFrame, CTkButton, CTkLabel, CTkSlider, CTkCheckBox, CTkEntry, CTkProgressBar)):
|
@ -1,203 +0,0 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
|
||||
from .customtkinter_tk import CTk
|
||||
from .customtkinter_canvas import CTkCanvas
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from ..customtkinter_theme_manager import CTkThemeManager
|
||||
from ..customtkinter_settings import CTkSettings
|
||||
from ..customtkinter_draw_engine import CTkDrawEngine
|
||||
|
||||
|
||||
class CTkFrame(tkinter.Frame):
|
||||
def __init__(self, *args,
|
||||
bg_color=None,
|
||||
fg_color="default_theme",
|
||||
border_color="default_theme",
|
||||
border_width="default_theme",
|
||||
corner_radius="default_theme",
|
||||
width=200,
|
||||
height=200,
|
||||
**kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Frame)) and not isinstance(self.master, (CTk, CTkFrame)):
|
||||
master_old_configure = self.master.config
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribut>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.change_appearance_mode, self)
|
||||
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.border_color = CTkThemeManager.theme["color"]["frame_border"] if border_color == "default_theme" else border_color
|
||||
|
||||
if fg_color == "default_theme":
|
||||
if isinstance(self.master, CTkFrame):
|
||||
if self.master.fg_color == CTkThemeManager.theme["color"]["frame_low"]:
|
||||
self.fg_color = CTkThemeManager.theme["color"]["frame_high"]
|
||||
else:
|
||||
self.fg_color = CTkThemeManager.theme["color"]["frame_low"]
|
||||
else:
|
||||
self.fg_color = CTkThemeManager.theme["color"]["frame_low"]
|
||||
else:
|
||||
self.fg_color = fg_color
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.configure(width=self.width, height=self.height)
|
||||
|
||||
self.corner_radius = CTkThemeManager.theme["shape"]["frame_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||
self.border_width = CTkThemeManager.theme["shape"]["frame_border_width"] if border_width == "default_theme" else border_width
|
||||
|
||||
if self.corner_radius * 2 > self.height:
|
||||
self.corner_radius = self.height / 2
|
||||
elif self.corner_radius * 2 > self.width:
|
||||
self.corner_radius = self.width / 2
|
||||
|
||||
if self.corner_radius >= self.border_width:
|
||||
self.inner_corner_radius = self.corner_radius - self.border_width
|
||||
else:
|
||||
self.inner_corner_radius = 0
|
||||
|
||||
self.canvas = CTkCanvas(master=self,
|
||||
highlightthickness=0,
|
||||
width=self.width,
|
||||
height=self.height)
|
||||
self.canvas.place(x=0, y=0, relwidth=1, relheight=1)
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
|
||||
|
||||
self.bind('<Configure>', self.update_dimensions)
|
||||
|
||||
self.draw()
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.change_appearance_mode)
|
||||
super().destroy()
|
||||
|
||||
def winfo_children(self):
|
||||
""" winfo_children of CTkFrame without self.canvas widget,
|
||||
because it's not a child but part of the CTkFrame itself """
|
||||
|
||||
child_widgets = super().winfo_children()
|
||||
try:
|
||||
child_widgets.remove(self.canvas)
|
||||
return child_widgets
|
||||
except ValueError:
|
||||
return child_widgets
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkFrame): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def update_dimensions(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
self.width = event.width
|
||||
self.height = event.height
|
||||
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
|
||||
requires_recoloring = self.draw_engine.draw_rounded_rect_with_border(self.width, self.height, self.corner_radius, self.border_width)
|
||||
|
||||
self.canvas.itemconfig("inner_parts",
|
||||
fill=CTkThemeManager.single_color(self.fg_color, self.appearance_mode),
|
||||
outline=CTkThemeManager.single_color(self.fg_color, self.appearance_mode))
|
||||
self.canvas.itemconfig("border_parts",
|
||||
fill=CTkThemeManager.single_color(self.border_color, self.appearance_mode),
|
||||
outline=CTkThemeManager.single_color(self.border_color, self.appearance_mode))
|
||||
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||
|
||||
self.canvas.tag_lower("inner_parts")
|
||||
self.canvas.tag_lower("border_parts")
|
||||
|
||||
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 "fg_color" in kwargs:
|
||||
self.fg_color = kwargs["fg_color"]
|
||||
require_redraw = True
|
||||
del kwargs["fg_color"]
|
||||
|
||||
# check if CTk widgets are children of the frame and change their bg_color to new frame fg_color
|
||||
from .customtkinter_slider import CTkSlider
|
||||
from .customtkinter_progressbar import CTkProgressBar
|
||||
from .customtkinter_label import CTkLabel
|
||||
from .customtkinter_entry import CTkEntry
|
||||
from customtkinter.widgets.customtkinter_checkbox import CTkCheckBox
|
||||
from customtkinter.widgets.customtkinter_button import CTkButton
|
||||
|
||||
for child in self.winfo_children():
|
||||
if isinstance(child, (CTkButton, CTkLabel, CTkSlider, CTkCheckBox, CTkEntry, CTkProgressBar, CTkFrame)):
|
||||
child.configure(bg_color=self.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 "corner_radius" in kwargs:
|
||||
self.corner_radius = kwargs["corner_radius"]
|
||||
require_redraw = True
|
||||
del kwargs["corner_radius"]
|
||||
|
||||
super().configure(*args, **kwargs)
|
||||
|
||||
if require_redraw:
|
||||
self.draw()
|
||||
|
||||
def change_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, CTkFrame):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
111
customtkinter/widgets/widget_base_class.py
Normal file
111
customtkinter/widgets/widget_base_class.py
Normal file
@ -0,0 +1,111 @@
|
||||
import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
|
||||
from .ctk_tk import CTk
|
||||
from .ctk_toplevel import CTkToplevel
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
|
||||
|
||||
class CTkBaseClass(tkinter.Frame):
|
||||
def __init__(self, *args, bg_color=None, width, height, **kwargs):
|
||||
super().__init__(*args, width=width, height=height, **kwargs) # set desired size of underlying tkinter.Frame
|
||||
|
||||
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
|
||||
self.width = width # width and height in pixel, represent current size of the widget (not the desired size by init)
|
||||
self.height = height
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||
|
||||
# overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget too
|
||||
if isinstance(self.master, (tkinter.Tk, tkinter.Toplevel, tkinter.Frame)) and not isinstance(self.master, (CTkBaseClass, CTk, CTkToplevel)):
|
||||
master_old_configure = self.master.config
|
||||
|
||||
def new_configure(*args, **kwargs):
|
||||
if "bg" in kwargs:
|
||||
self.configure(bg_color=kwargs["bg"])
|
||||
elif "background" in kwargs:
|
||||
self.configure(bg_color=kwargs["background"])
|
||||
|
||||
# args[0] is dict when attribute gets changed by widget[<attribute>] syntax
|
||||
elif len(args) > 0 and type(args[0]) == dict:
|
||||
if "bg" in args[0]:
|
||||
self.configure(bg_color=args[0]["bg"])
|
||||
elif "background" in args[0]:
|
||||
self.configure(bg_color=args[0]["background"])
|
||||
master_old_configure(*args, **kwargs)
|
||||
|
||||
self.master.config = new_configure
|
||||
self.master.configure = new_configure
|
||||
|
||||
def destroy(self):
|
||||
AppearanceModeTracker.remove(self.set_appearance_mode)
|
||||
super().destroy()
|
||||
|
||||
def config(self, *args, **kwargs):
|
||||
self.configure(*args, **kwargs)
|
||||
|
||||
def configure(self, *args, **kwargs):
|
||||
""" basic configure with bg_color support, to be overridden """
|
||||
|
||||
require_redraw = False
|
||||
|
||||
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"]
|
||||
|
||||
super().configure(*args, **kwargs)
|
||||
|
||||
if require_redraw:
|
||||
self.draw()
|
||||
|
||||
def update_dimensions(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != event.width or self.height != event.height:
|
||||
self.width = event.width # adjust current size according to new size given by event
|
||||
self.height = event.height
|
||||
|
||||
self.draw(no_color_updates=True) # faster drawing without color changes
|
||||
|
||||
def detect_color_of_master(self):
|
||||
""" detect color of self.master widget to set correct bg_color """
|
||||
|
||||
if isinstance(self.master, CTkBaseClass) and hasattr(self.master, "fg_color"): # master is CTkFrame
|
||||
return self.master.fg_color
|
||||
|
||||
elif isinstance(self.master, (ttk.Frame, ttk.LabelFrame, ttk.Notebook)): # master is ttk widget
|
||||
try:
|
||||
ttk_style = ttk.Style()
|
||||
return ttk_style.lookup(self.master.winfo_class(), 'background')
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
else: # master is normal tkinter widget
|
||||
try:
|
||||
return self.master.cget("bg") # try to get bg color by .cget() method
|
||||
except Exception:
|
||||
return "#FFFFFF", "#000000"
|
||||
|
||||
def set_appearance_mode(self, mode_string):
|
||||
if mode_string.lower() == "dark":
|
||||
self.appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self.appearance_mode = 0
|
||||
|
||||
if isinstance(self.master, (CTkBaseClass, CTk)) and hasattr(self.master, "fg_color"):
|
||||
self.bg_color = self.master.fg_color
|
||||
else:
|
||||
self.bg_color = self.master.cget("bg")
|
||||
|
||||
self.draw()
|
||||
|
||||
def draw(self, no_color_updates=False):
|
||||
""" abstract of draw method to be overridden """
|
||||
pass
|
||||
|
||||
|
@ -10,9 +10,9 @@ app.title("CTkDialog Test")
|
||||
|
||||
|
||||
def change_mode():
|
||||
if customtkinter.get_appearance_mode().lower() == "dark":
|
||||
if c1.get() == 0:
|
||||
customtkinter.set_appearance_mode("light")
|
||||
elif customtkinter.get_appearance_mode().lower() == "light":
|
||||
else:
|
||||
customtkinter.set_appearance_mode("dark")
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user