Added .cget() methods to all widgets and changed text_font to font for all widgets

This commit is contained in:
Tom Schimansky 2022-10-03 00:33:06 +02:00
parent 8b6f9a1d7e
commit bfc42c25ef
22 changed files with 725 additions and 246 deletions

View File

@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased - 2022-10-2
### Added
- added .cget() method to all widgets and windows
### Changed
- changed 'text_font' attribute to 'font' in all widgets
- changed 'dropdown_color' attribute to 'dropdown_fg_color' for combobox, optionmenu
- changed 'orient' attribute of CTkProgressBar and CTkSlider to 'orientation'
### Removed
- removed setter and getter functions like set_text in CTkButton
### Fixed
## [4.6.0] - 2022-09-17
### Added
- CTkProgressBar indeterminate mode, automatic progress loop with .start() and .stop()

View File

@ -16,24 +16,26 @@ class CTkButton(CTkBaseClass):
"""
def __init__(self, *args,
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
hover_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
text: str = "CTkButton",
font: any = "default_theme",
textvariable: tkinter.Variable = None,
text_font: any = "default_theme",
image: tkinter.PhotoImage = None,
hover: bool = True,
compound: str = "left",
state: str = "normal",
hover: bool = True,
command: Callable = None,
compound: str = "left",
**kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
@ -55,7 +57,7 @@ class CTkButton(CTkBaseClass):
self._image_label = None
self._text = text
self._text_label = None
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# callback and hover functionality
self._command = command
@ -141,7 +143,7 @@ class CTkButton(CTkBaseClass):
if self._text_label is None:
self._text_label = tkinter.Label(master=self,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
text=self._text,
textvariable=self._textvariable)
@ -249,10 +251,10 @@ class CTkButton(CTkBaseClass):
else:
self._text_label.configure(text=self._text)
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
if "font" in kwargs:
self._font = kwargs.pop("font")
if self._text_label is not None:
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
if "state" in kwargs:
self._state = kwargs.pop("state")
@ -303,37 +305,41 @@ class CTkButton(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, key: str) -> any:
if key == "fg_color":
return self._fg_color
elif key == "hover_color":
return self._hover_color
elif key == "border_color":
return self._border_color
elif key == "text_color":
return self._text_color
elif key == "text_color_disabled":
return self._text_color_disabled
elif key == "text":
return self._text
elif key == "textvariable":
return self._textvariable
elif key == "text_font":
return self._text_font
elif key == "command":
return self._command
elif key == "hover":
return self._hover
elif key == "border_width":
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif key == "image":
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "hover_color":
return self._hover_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text_color_disabled":
return self._text_color_disabled
elif attribute_name == "text":
return self._text
elif attribute_name == "font":
return self._font
elif attribute_name == "textvariable":
return self._textvariable
elif attribute_name == "image":
return self._image
elif key == "compound":
return self._compound
elif key == "state":
elif attribute_name == "state":
return self._state
elif attribute_name == "hover":
return self._hover
elif attribute_name == "command":
return self._command
elif attribute_name == "compound":
return self._compound
else:
return super().cget(key)
return super().cget(attribute_name)
def _set_cursor(self):
if Settings.cursor_manipulation_enabled:

View File

@ -16,26 +16,28 @@ class CTkCheckBox(CTkBaseClass):
"""
def __init__(self, *args,
width: int = 24,
height: int = 24,
corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
border_width: Union[int, str] = "default_theme",
checkmark_color: Union[str, Tuple[str, str]] = "default_theme",
width: int = 24,
height: int = 24,
corner_radius: Union[int, str] = "default_theme",
text_font: any = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkCheckBox",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkCheckBox",
font: any = "default_theme",
textvariable: tkinter.Variable = None,
state: str = tkinter.NORMAL,
hover: bool = True,
command: Callable = None,
state: str = tkinter.NORMAL,
onvalue: Union[int, str] = 1,
offvalue: Union[int, str] = 0,
variable: tkinter.Variable = None,
textvariable: tkinter.Variable = None,
**kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
@ -56,7 +58,7 @@ class CTkCheckBox(CTkBaseClass):
self._text_label: Union[tkinter.Label, None] = None
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self._text_color_disabled = ThemeManager.theme["color"]["text_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# callback and hover functionality
self._command = command
@ -98,7 +100,7 @@ class CTkCheckBox(CTkBaseClass):
bd=0,
text=self._text,
justify=tkinter.LEFT,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
textvariable=self._textvariable)
self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w")
self._text_label["anchor"] = "w"
@ -119,7 +121,7 @@ class CTkCheckBox(CTkBaseClass):
super()._set_scaling(*args, **kwargs)
self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6))
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
self._canvas.delete("checkmark")
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
@ -183,10 +185,10 @@ class CTkCheckBox(CTkBaseClass):
self._text = kwargs.pop("text")
self._text_label.configure(text=self._text)
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
if "font" in kwargs:
self._font = kwargs.pop("font")
if self._text_label is not None:
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
if "state" in kwargs:
self._state = kwargs.pop("state")
@ -229,6 +231,44 @@ class CTkCheckBox(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "hover_color":
return self._hover_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "checkmark_color":
return self._checkmark_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text_color_disabled":
return self._text_color_disabled
elif attribute_name == "text":
return self._text
elif attribute_name == "font":
return self._font
elif attribute_name == "textvariable":
return self._textvariable
elif attribute_name == "state":
return self._state
elif attribute_name == "hover":
return self._hover
elif attribute_name == "onvalue":
return self._onvalue
elif attribute_name == "offvalue":
return self._offvalue
elif attribute_name == "variable":
return self._variable
else:
return super().cget(attribute_name)
def _set_cursor(self):
if Settings.cursor_manipulation_enabled:
if self._state == tkinter.DISABLED:

View File

@ -9,6 +9,8 @@ from ..settings import Settings
from ..draw_engine import DrawEngine
from .widget_base_class import CTkBaseClass
from .widget_helper_functions import filter_dict_by_set
class CTkComboBox(CTkBaseClass):
"""
@ -17,27 +19,29 @@ class CTkComboBox(CTkBaseClass):
"""
def __init__(self, *args,
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
button_color: Union[str, Tuple[str, str]] = "default_theme",
button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_fg_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_hover_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_text_color: Union[str, Tuple[str, str]] = "default_theme",
variable: tkinter.Variable = None,
values: List[str] = None,
command: Callable = None,
width: int = 140,
height: int = 28,
corner_radius: int = "default_theme",
border_width: int = "default_theme",
text_font: any = "default_theme",
dropdown_text_font: any = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
hover: bool = True,
font: any = "default_theme",
dropdown_text_font: any = "default_theme",
values: List[str] = None,
state: str = tkinter.NORMAL,
hover: bool = True,
variable: tkinter.Variable = None,
command: Callable = None,
**kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
@ -56,11 +60,11 @@ class CTkComboBox(CTkBaseClass):
# text and font
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self._text_color_disabled = ThemeManager.theme["color"]["text_button_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# callback and hover functionality
self._command = command
self._textvariable = variable
self._variable = variable
self._state = state
self._hover = hover
@ -72,10 +76,10 @@ class CTkComboBox(CTkBaseClass):
self._dropdown_menu = DropdownMenu(master=self,
values=self._values,
command=self._dropdown_callback,
fg_color=dropdown_color,
fg_color=dropdown_fg_color,
hover_color=dropdown_hover_color,
text_color=dropdown_text_color,
text_font=dropdown_text_font)
font=dropdown_text_font)
# configure grid system (1x1)
self.grid_rowconfigure(0, weight=1)
@ -93,7 +97,7 @@ class CTkComboBox(CTkBaseClass):
width=1,
bd=0,
highlightthickness=0,
font=self._apply_font_scaling(self._text_font))
font=self._apply_font_scaling(self._font))
left_section_width = self._current_width - self._current_height
self._entry.grid(row=0, column=0, rowspan=1, columnspan=1, sticky="ew",
padx=(max(self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(3)),
@ -116,15 +120,15 @@ class CTkComboBox(CTkBaseClass):
self._canvas.tag_bind("dropdown_arrow", "<Button-1>", self._clicked)
self.bind('<Configure>', self._update_dimensions_event)
if self._textvariable is not None:
self._entry.configure(textvariable=self._textvariable)
if self._variable is not None:
self._entry.configure(textvariable=self._variable)
def _set_scaling(self, *args, **kwargs):
super()._set_scaling(*args, **kwargs)
# change entry font size and grid padding
left_section_width = self._current_width - self._current_height
self._entry.configure(font=self._apply_font_scaling(self._text_font))
self._entry.configure(font=self._apply_font_scaling(self._font))
self._entry.grid(row=0, column=0, rowspan=1, columnspan=1, sticky="ew",
padx=(max(self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(3)),
max(self._apply_widget_scaling(self._current_width - left_section_width + 3), self._apply_widget_scaling(3))))
@ -210,16 +214,16 @@ class CTkComboBox(CTkBaseClass):
self._text_color = kwargs.pop("text_color")
require_redraw = True
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._entry.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._entry.configure(font=self._apply_font_scaling(self._font))
if "command" in kwargs:
self._command = kwargs.pop("command")
if "variable" in kwargs:
self._textvariable = kwargs.pop("variable")
self._entry.configure(textvariable=self._textvariable)
self._variable = kwargs.pop("variable")
self._entry.configure(textvariable=self._variable)
if "width" in kwargs:
self._set_dimensions(width=kwargs.pop("width"))
@ -231,8 +235,8 @@ class CTkComboBox(CTkBaseClass):
self._values = kwargs.pop("values")
self._dropdown_menu.configure(values=self._values)
if "dropdown_color" in kwargs:
self._dropdown_menu.configure(fg_color=kwargs.pop("dropdown_color"))
if "dropdown_fg_color" in kwargs:
self._dropdown_menu.configure(fg_color=kwargs.pop("dropdown_fg_color"))
if "dropdown_hover_color" in kwargs:
self._dropdown_menu.configure(hover_color=kwargs.pop("dropdown_hover_color"))
@ -245,6 +249,48 @@ class CTkComboBox(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "button_color":
return self._button_color
elif attribute_name == "button_hover_color":
return self._button_hover_color
elif attribute_name == "dropdown_fg_color":
return self._dropdown_menu.cget("fg_color")
elif attribute_name == "dropdown_hover_color":
return self._dropdown_menu.cget("hover_color")
elif attribute_name == "dropdown_text_color":
return self._dropdown_menu.cget("text_color")
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text_color_disabled":
return self._text_color_disabled
elif attribute_name == "font":
return self._font
elif attribute_name == "dropdown_text_font":
return self._dropdown_menu.cget("text_font")
elif attribute_name == "values":
return self._values
elif attribute_name == "state":
return self._state
elif attribute_name == "hover":
return self._hover
elif attribute_name == "variable":
return self._variable
elif attribute_name == "command":
return self._command
else:
return super().cget(attribute_name)
def _on_enter(self, event=0):
if self._hover is True and self._state == tkinter.NORMAL and len(self._values) > 0:
if sys.platform == "darwin" and len(self._values) > 0 and Settings.cursor_manipulation_enabled:

View File

@ -6,6 +6,8 @@ from ..theme_manager import ThemeManager
from ..draw_engine import DrawEngine
from .widget_base_class import CTkBaseClass
from .widget_helper_functions import *
class CTkEntry(CTkBaseClass):
"""
@ -13,23 +15,33 @@ class CTkEntry(CTkBaseClass):
For detailed information check out the documentation.
"""
# attributes that are passed to and managed by the tkinter entry only:
_valid_tk_entry_attributes = {"exportselection", "font", "highlightbackground",
"highlightcolor", "insertbackground", "insertborderwidth",
"insertofftime", "insertontime", "insertwidth",
"justify", "selectbackground", "selectborderwidth",
"selectforeground", "show", "takefocus", "validate",
"validatecommand", "xscrollcommand"}
def __init__(self, *args,
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
placeholder_text_color: Union[str, Tuple[str, str]] = "default_theme",
text_font: Union[str, Tuple[str, str]] = "default_theme",
placeholder_text: str = None,
corner_radius: int = "default_theme",
border_width: int = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
width: int = 140,
height: int = 28,
state: str = tkinter.NORMAL,
corner_radius: int = "default_theme",
border_width: int = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
placeholder_text_color: Union[str, Tuple[str, str]] = "default_theme",
textvariable: tkinter.Variable = None,
placeholder_text: str = None,
font: Union[str, Tuple[str, str]] = "default_theme",
state: str = tkinter.NORMAL,
**kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
# 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.pop("master"))
else:
@ -43,7 +55,7 @@ class CTkEntry(CTkBaseClass):
self._fg_color = ThemeManager.theme["color"]["entry"] if fg_color == "default_theme" else fg_color
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self._placeholder_text_color = ThemeManager.theme["color"]["entry_placeholder_text"] if placeholder_text_color == "default_theme" else placeholder_text_color
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
self._border_color = ThemeManager.theme["color"]["entry_border"] if border_color == "default_theme" else border_color
# shape
@ -71,10 +83,10 @@ class CTkEntry(CTkBaseClass):
bd=0,
width=1,
highlightthickness=0,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
state=self._state,
textvariable=self._textvariable,
**kwargs)
**filter_dict_by_set(kwargs, self._valid_tk_entry_attributes))
self._entry.grid(column=0, row=0, sticky="nswe",
padx=self._apply_widget_scaling(self._corner_radius) if self._corner_radius >= 6 else self._apply_widget_scaling(6),
pady=(self._apply_widget_scaling(self._border_width), self._apply_widget_scaling(self._border_width + 1)))
@ -89,7 +101,7 @@ class CTkEntry(CTkBaseClass):
def _set_scaling(self, *args, **kwargs):
super()._set_scaling(*args, **kwargs)
self._entry.configure(font=self._apply_font_scaling(self._text_font))
self._entry.configure(font=self._apply_font_scaling(self._font))
self._entry.grid(column=0, row=0, sticky="we",
padx=self._apply_widget_scaling(self._corner_radius) if self._corner_radius >= 6 else self._apply_widget_scaling(6))
@ -144,6 +156,8 @@ class CTkEntry(CTkBaseClass):
return self.configure(*args, **kwargs)
def configure(self, require_redraw=False, **kwargs):
self._entry.configure(**filter_dict_by_set(kwargs, self._valid_tk_entry_attributes))
if "state" in kwargs:
self._state = kwargs.pop("state")
self._entry.configure(state=self._state)
@ -193,9 +207,9 @@ class CTkEntry(CTkBaseClass):
self._textvariable = kwargs.pop("textvariable")
self._entry.configure(textvariable=self._textvariable)
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._entry.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._entry.configure(font=self._apply_font_scaling(self._font))
if "show" in kwargs:
if self._placeholder_text_active:
@ -203,12 +217,40 @@ class CTkEntry(CTkBaseClass):
else:
self._entry.configure(show=kwargs.pop("show"))
if "_bg_color" in kwargs:
super().configure(bg_color=kwargs.pop("_bg_color"), require_redraw=require_redraw)
else:
super().configure(require_redraw=require_redraw)
super().configure(require_redraw=require_redraw, **kwargs)
self._entry.configure(**kwargs) # pass remaining kwargs to entry
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "placeholder_text_color":
return self._placeholder_text_color
elif attribute_name == "textvariable":
return self._textvariable
elif attribute_name == "placeholder_text":
return self._placeholder_text
elif attribute_name == "text_font":
return self._font
elif attribute_name == "state":
return self._state
elif attribute_name in ["exportselection", "font", "highlightbackground",
"highlightcolor", "insertbackground",
"insertborderwidth", "insertofftime", "insertontime",
"insertwidth", "justify", "selectbackground",
"selectborderwidth", "selectforeground", "show",
"takefocus", "validate", "validatecommand",
"xscrollcommand"]:
return self._entry.cget(attribute_name)
def bind(self, *args, **kwargs):
self._entry.bind(*args, **kwargs)

View File

@ -15,13 +15,15 @@ class CTkFrame(CTkBaseClass):
"""
def __init__(self, *args,
width: int = 200,
height: int = 200,
corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
border_width: Union[int, str] = "default_theme",
corner_radius: Union[int, str] = "default_theme",
width: int = 200,
height: int = 200,
overwrite_preferred_drawing_method: str = None,
**kwargs):
@ -144,3 +146,16 @@ class CTkFrame(CTkBaseClass):
self._set_dimensions(height=kwargs.pop("height"))
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
else:
return super().cget(attribute_name)

View File

@ -13,15 +13,20 @@ class CTkLabel(CTkBaseClass):
For detailed information check out the documentation.
"""
# attributes that are passed to and managed by the tkinter entry only:
_valid_tk_label_attributes = {"compound", "cursor", ""}
def __init__(self, *args,
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
corner_radius: Union[int, str] = "default_theme",
width: int = 140,
height: int = 28,
text: str = "CTkLabel",
text_font: any = "default_theme",
font: any = "default_theme",
anchor: str = "center", # label anchor: center, n, e, s, w
**kwargs):
@ -41,7 +46,7 @@ class CTkLabel(CTkBaseClass):
# text
self._anchor = anchor
self._text = text
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# configure grid system (1x1)
self.grid_rowconfigure(0, weight=1)
@ -59,7 +64,7 @@ class CTkLabel(CTkBaseClass):
bd=0,
anchor=self._anchor,
text=self._text,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
**kwargs)
text_label_grid_sticky = self._anchor if self._anchor != "center" else ""
self._text_label.grid(row=0, column=0, padx=self._apply_widget_scaling(self._corner_radius),
@ -72,7 +77,7 @@ class CTkLabel(CTkBaseClass):
super()._set_scaling(*args, **kwargs)
self._canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
text_label_grid_sticky = self._anchor if self._anchor != "center" else ""
self._text_label.grid(row=0, column=0, padx=self._apply_widget_scaling(self._corner_radius),
sticky=text_label_grid_sticky)
@ -124,9 +129,9 @@ class CTkLabel(CTkBaseClass):
self._text = kwargs.pop("text")
self._text_label.configure(text=self._text)
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._text_label.configure(font=self._apply_font_scaling(self._font))
if "fg_color" in kwargs:
self._fg_color = kwargs.pop("fg_color")
@ -148,3 +153,21 @@ class CTkLabel(CTkBaseClass):
super().configure(require_redraw=require_redraw)
self._text_label.configure(**kwargs) # pass remaining kwargs to label
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text":
return self._text
elif attribute_name == "font":
return self._font
elif attribute_name == "anchor":
return self._anchor
else:
return super().cget(attribute_name)

View File

@ -12,30 +12,32 @@ from .dropdown_menu import DropdownMenu
class CTkOptionMenu(CTkBaseClass):
"""
Optionemnu with rounded corners, dropdown menu, variable support, command.
Optionmenu with rounded corners, dropdown menu, variable support, command.
For detailed information check out the documentation.
"""
def __init__(self, *args,
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
button_color: Union[str, Tuple[str, str]] = "default_theme",
button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
dropdown_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_fg_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_hover_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_text_color: Union[str, Tuple[str, str]] = "default_theme",
variable: tkinter.Variable = None,
values: list = None,
command: Callable = None,
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
text_font: any = "default_theme",
font: any = "default_theme",
dropdown_text_font: any = "default_theme",
hover: bool = True,
values: list = None,
variable: tkinter.Variable = None,
state: str = tkinter.NORMAL,
hover: bool = True,
command: Callable = None,
dynamic_resizing: bool = True,
**kwargs):
@ -53,7 +55,7 @@ class CTkOptionMenu(CTkBaseClass):
# text and font
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self._text_color_disabled = ThemeManager.theme["color"]["text_button_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
self._dropdown_text_font = dropdown_text_font
# callback and hover functionality
@ -78,10 +80,10 @@ class CTkOptionMenu(CTkBaseClass):
self._dropdown_menu = DropdownMenu(master=self,
values=self._values,
command=self._dropdown_callback,
fg_color=dropdown_color,
fg_color=dropdown_fg_color,
hover_color=dropdown_hover_color,
text_color=dropdown_text_color,
text_font=dropdown_text_font)
font=dropdown_text_font)
# configure grid system (1x1)
self.grid_rowconfigure(0, weight=1)
@ -96,7 +98,7 @@ class CTkOptionMenu(CTkBaseClass):
left_section_width = self._current_width - self._current_height
self._text_label = tkinter.Label(master=self,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
anchor="w",
text=self._current_value)
self._text_label.grid(row=0, column=0, sticky="w",
@ -137,7 +139,7 @@ class CTkOptionMenu(CTkBaseClass):
# change label text size and grid padding
left_section_width = self._current_width - self._current_height
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
self._text_label.grid(row=0, column=0, sticky="w",
padx=(max(self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(3)),
max(self._apply_widget_scaling(self._current_width - left_section_width + 3), self._apply_widget_scaling(3))))
@ -215,9 +217,9 @@ class CTkOptionMenu(CTkBaseClass):
self._text_color = kwargs.pop("text_color")
require_redraw = True
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._text_label.configure(font=self._apply_font_scaling(self._font))
if "command" in kwargs:
self._command = kwargs.pop("command")
@ -267,6 +269,46 @@ class CTkOptionMenu(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "button_color":
return self._button_color
elif attribute_name == "button_hover_color":
return self._button_hover_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text_color_disabled":
return self._text_color_disabled
elif attribute_name == "dropdown_fg_color":
return self._dropdown_menu.cget("fg_color")
elif attribute_name == "dropdown_hover_color":
return self._dropdown_menu.cget("hover_color")
elif attribute_name == "dropdown_text_color":
return self._dropdown_menu.cget("text_color")
elif attribute_name == "font":
return self._font
elif attribute_name == "dropdown_text_font":
return self._dropdown_menu.cget("text_font")
elif attribute_name == "values":
return self._values
elif attribute_name == "variable":
return self._variable
elif attribute_name == "state":
return self._state
elif attribute_name == "hover":
return self._hover
elif attribute_name == "command":
return self._command
elif attribute_name == "dynamic_resizing":
return self._dynamic_resizing
else:
return super().cget(attribute_name)
def _open_dropdown_menu(self):
self._dropdown_menu.open(self.winfo_rootx(),
self.winfo_rooty() + self._apply_widget_scaling(self._current_height + 0))

View File

@ -16,16 +16,18 @@ class CTkProgressBar(CTkBaseClass):
"""
def __init__(self, *args,
bg_color: Union[str, Tuple[str, str], None] = None,
border_color: Union[str, Tuple[str, str]] = "default_theme",
fg_color: Union[str, Tuple[str, str]] = "default_theme",
progress_color: Union[str, Tuple[str, str]] = "default_theme",
corner_radius: Union[str, Tuple[str, str]] = "default_theme",
width: Union[int, str] = "default_init",
height: Union[int, str] = "default_init",
corner_radius: Union[str, Tuple[str, str]] = "default_theme",
border_width: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
progress_color: Union[str, Tuple[str, str]] = "default_theme",
variable: tkinter.Variable = None,
orient: str = "horizontal",
orientation: str = "horizontal",
mode: str = "determinate",
determinate_speed: float = 1,
indeterminate_speed: float = 1,
@ -33,12 +35,12 @@ class CTkProgressBar(CTkBaseClass):
# set default dimensions according to orientation
if width == "default_init":
if orient.lower() == "vertical":
if orientation.lower() == "vertical":
width = 8
else:
width = 200
if height == "default_init":
if orient.lower() == "vertical":
if orientation.lower() == "vertical":
height = 200
else:
height = 8
@ -65,7 +67,7 @@ class CTkProgressBar(CTkBaseClass):
self._indeterminate_width: float = 0.4 # range 0-1
self._indeterminate_speed = indeterminate_speed # range 0-1 to travel in 50ms
self._loop_running: bool = False
self._orient = orient
self._orientation = orientation
self._mode = mode # "determinate" or "indeterminate"
self.grid_rowconfigure(0, weight=1)
@ -110,9 +112,9 @@ class CTkProgressBar(CTkBaseClass):
super().destroy()
def _draw(self, no_color_updates=False):
if self._orient.lower() == "horizontal":
if self._orientation.lower() == "horizontal":
orientation = "w"
elif self._orient.lower() == "vertical":
elif self._orientation.lower() == "vertical":
orientation = "s"
else:
orientation = "w"
@ -200,6 +202,32 @@ class CTkProgressBar(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "progress_color":
return self._progress_color
elif attribute_name == "variable":
return self._variable
elif attribute_name == "orientation":
return self._orientation
elif attribute_name == "mode":
return self._mode
elif attribute_name == "determinate_speed":
return self._determinate_speed
elif attribute_name == "indeterminate_speed":
return self._indeterminate_speed
else:
return super().cget(attribute_name)
def _variable_callback(self, var_name, index, mode):
if not self._variable_callback_blocked:
self.set(self._variable.get(), from_variable_callback=True)

View File

@ -16,25 +16,27 @@ class CTkRadioButton(CTkBaseClass):
"""
def __init__(self, *args,
width: int = 22,
height: int = 22,
corner_radius: Union[int, str] = "default_theme",
border_width_unchecked: Union[int, str] = "default_theme",
border_width_checked: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
border_width_unchecked: Union[int, str] = "default_theme",
border_width_checked: Union[int, str] = "default_theme",
width: int = 22,
height: int = 22,
corner_radius: Union[int, str] = "default_theme",
text_font: any = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkRadioButton",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkRadioButton",
font: any = "default_theme",
textvariable: tkinter.Variable = None,
variable: tkinter.Variable = None,
value: Union[int, str] = 0,
state: str = tkinter.NORMAL,
hover: bool = True,
command: Callable = None,
state: str = tkinter.NORMAL,
value: Union[int, str] = 0,
variable: tkinter.Variable = None,
textvariable: tkinter.Variable = None,
**kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
@ -56,7 +58,7 @@ class CTkRadioButton(CTkBaseClass):
self._text_label: Union[tkinter.Label, None] = None
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self._text_color_disabled = ThemeManager.theme["color"]["text_disabled"] if text_color_disabled == "default_theme" else text_color_disabled
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# callback and control variables
self._command = command
@ -95,7 +97,7 @@ class CTkRadioButton(CTkBaseClass):
bd=0,
text=self._text,
justify=tkinter.LEFT,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
textvariable=self._textvariable)
self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w")
self._text_label["anchor"] = "w"
@ -115,7 +117,7 @@ class CTkRadioButton(CTkBaseClass):
super()._set_scaling(*args, **kwargs)
self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6))
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
self._canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
@ -164,9 +166,9 @@ class CTkRadioButton(CTkBaseClass):
self._text = kwargs.pop("text")
self._text_label.configure(text=self._text)
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._text_label.configure(font=self._apply_font_scaling(self._font))
if "state" in kwargs:
self._state = kwargs.pop("state")
@ -213,6 +215,44 @@ class CTkRadioButton(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width_unchecked":
return self._border_width_unchecked
elif attribute_name == "border_width_checked":
return self._border_width_checked
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "hover_color":
return self._hover_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text_color_disabled":
return self._text_color_disabled
elif attribute_name == "text":
return self._text
elif attribute_name == "font":
return self._font
elif attribute_name == "textvariable":
return self._textvariable
elif attribute_name == "variable":
return self._variable
elif attribute_name == "value":
return self._value
elif attribute_name == "state":
return self._state
elif attribute_name == "hover":
return self._hover
elif attribute_name == "command":
return self._command
else:
return super().cget(attribute_name)
def _set_cursor(self):
if Settings.cursor_manipulation_enabled:
if self._state == tkinter.DISABLED:

View File

@ -15,18 +15,20 @@ class CTkScrollbar(CTkBaseClass):
"""
def __init__(self, *args,
width: Union[int, str] = "default_init",
height: Union[int, str] = "default_init",
corner_radius: Union[int, str] = "default_theme",
border_spacing: Union[int, str] = "default_theme",
minimum_pixel_length: int = 20,
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
scrollbar_color: Union[str, Tuple[str, str]] = "default_theme",
scrollbar_hover_color: Union[str, Tuple[str, str]] = "default_theme",
border_spacing: Union[int, str] = "default_theme",
corner_radius: Union[int, str] = "default_theme",
width: Union[int, str] = "default_init",
height: Union[int, str] = "default_init",
minimum_pixel_length: int = 20,
orientation: str = "vertical",
command: Callable = None,
hover: bool = True,
command: Callable = None,
orientation: str = "vertical",
**kwargs):
# set default dimensions according to orientation
@ -183,6 +185,30 @@ class CTkScrollbar(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_spacing":
return self._border_spacing
elif attribute_name == "minimum_pixel_length":
return self._minimum_pixel_length
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "scrollbar_color":
return self._scrollbar_color
elif attribute_name == "scrollbar_hover_color":
return self._scrollbar_hover_color
elif attribute_name == "hover":
return self._hover
elif attribute_name == "command":
return self._command
elif attribute_name == "orientation":
return self._orientation
else:
return super().cget(attribute_name)
def _on_enter(self, event=0):
if self._hover is True:
self._hover_state = True

View File

@ -16,35 +16,37 @@ class CTkSlider(CTkBaseClass):
"""
def __init__(self, *args,
bg_color: Union[str, Tuple[str, str], None] = None,
border_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
progress_color: Union[str, Tuple[str, str], None] = "default_theme",
button_color: Union[str, Tuple[str, str]] = "default_theme",
button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
from_: int = 0,
to: int = 1,
number_of_steps: Union[int, None] = None,
width: Union[int, str] = "default_init",
height: Union[int, str] = "default_init",
corner_radius: Union[int, str] = "default_theme",
button_corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
button_length: Union[int, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str], None] = None,
progress_color: Union[str, Tuple[str, str], None] = "default_theme",
button_color: Union[str, Tuple[str, str]] = "default_theme",
button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
from_: int = 0,
to: int = 1,
state: str = "normal",
number_of_steps: Union[int, None] = None,
command: Callable = None,
variable: tkinter.Variable = None,
orient: str = "horizontal",
state: str = "normal",
orientation: str = "horizontal",
**kwargs):
# set default dimensions according to orientation
if width == "default_init":
if orient.lower() == "vertical":
if orientation.lower() == "vertical":
width = 16
else:
width = 200
if height == "default_init":
if orient.lower() == "vertical":
if orientation.lower() == "vertical":
height = 200
else:
height = 16
@ -65,7 +67,7 @@ class CTkSlider(CTkBaseClass):
self._border_width = ThemeManager.theme["shape"]["slider_border_width"] if border_width == "default_theme" else border_width
self._button_length = ThemeManager.theme["shape"]["slider_button_length"] if button_length == "default_theme" else button_length
self._value: float = 0.5 # initial value of slider in percent
self._orientation = orient
self._orientation = orientation
self._hover_state: bool = False
self._from_ = from_
self._to = to
@ -253,6 +255,44 @@ class CTkSlider(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "button_corner_radius":
return self._button_corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "button_length":
return self._button_length
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "progress_color":
return self._progress_color
elif attribute_name == "button_color":
return self._button_color
elif attribute_name == "button_hover_color":
return self._button_hover_color
elif attribute_name == "from_":
return self._from_
elif attribute_name == "to":
return self._to
elif attribute_name == "state":
return self._state
elif attribute_name == "number_of_steps":
return self._number_of_steps
elif attribute_name == "command":
return self._command
elif attribute_name == "variable":
return self._variable
elif attribute_name == "orientation":
return self._orientation
else:
return super().cget(attribute_name)
def _clicked(self, event=None):
if self._state == "normal":
if self._orientation.lower() == "horizontal":

View File

@ -16,26 +16,28 @@ class CTkSwitch(CTkBaseClass):
"""
def __init__(self, *args,
bg_color: Union[str, Tuple[str, str], None] = None,
border_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
progress_color: Union[str, Tuple[str, str]] = "default_theme",
button_color: Union[str, Tuple[str, str]] = "default_theme",
button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
width: int = 36,
height: int = 18,
text: str = "CTkSwitch",
text_font: any = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme",
button_length: Union[int, str] = "default_theme",
command: Callable = None,
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str], None] = None,
progress_color: Union[str, Tuple[str, str]] = "default_theme",
button_color: Union[str, Tuple[str, str]] = "default_theme",
button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkSwitch",
font: any = "default_theme",
textvariable: tkinter.Variable = None,
onvalue: Union[int, str] = 1,
offvalue: Union[int, str] = 0,
variable: tkinter.Variable = None,
textvariable: tkinter.Variable = None,
command: Callable = None,
state: str = tkinter.NORMAL,
**kwargs):
@ -54,7 +56,7 @@ class CTkSwitch(CTkBaseClass):
# text
self._text = text
self._text_label = None
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# shape
self._corner_radius = ThemeManager.theme["shape"]["switch_corner_radius"] if corner_radius == "default_theme" else corner_radius
@ -100,7 +102,7 @@ class CTkSwitch(CTkBaseClass):
bd=0,
text=self._text,
justify=tkinter.LEFT,
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
textvariable=self._textvariable)
self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w")
self._text_label["anchor"] = "w"
@ -120,7 +122,7 @@ class CTkSwitch(CTkBaseClass):
super()._set_scaling(*args, **kwargs)
self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6))
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
self._text_label.configure(font=self._apply_font_scaling(self._font))
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
self._canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
@ -213,9 +215,9 @@ class CTkSwitch(CTkBaseClass):
self._text = kwargs.pop("text")
self._text_label.configure(text=self._text)
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._text_label.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._text_label.configure(font=self._apply_font_scaling(self._font))
if "state" in kwargs:
self._state = kwargs.pop("state")
@ -270,6 +272,48 @@ class CTkSwitch(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "button_length":
return self._button_length
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "progress_color":
return self._progress_color
elif attribute_name == "button_color":
return self._button_color
elif attribute_name == "button_hover_color":
return self._button_hover_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "text_color_disabled":
return self._text_color_disabled
elif attribute_name == "text":
return self._text
elif attribute_name == "font":
return self._font
elif attribute_name == "textvariable":
return self._textvariable
elif attribute_name == "onvalue":
return self._onvalue
elif attribute_name == "offvalue":
return self._offvalue
elif attribute_name == "variable":
return self._variable
elif attribute_name == "command":
return self._command
elif attribute_name == "state":
return self._state
else:
return super().cget(attribute_name)
def toggle(self, event=None):
if self._state is not tkinter.DISABLED:
if self._check_state is True:

View File

@ -1,5 +1,5 @@
import tkinter
from typing import Union, Tuple, Callable
from typing import Union, Tuple
from .ctk_canvas import CTkCanvas
from ..theme_manager import ThemeManager
@ -14,15 +14,17 @@ class CTkTextbox(CTkBaseClass):
"""
def __init__(self, *args,
width: int = 200,
height: int = 200,
corner_radius: Union[str, str] = "default_theme",
border_width: Union[str, str] = "default_theme",
bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme",
border_width: Union[str, str] = "default_theme",
corner_radius: Union[str, str] = "default_theme",
text_font: any = "default_theme",
text_color: Union[str, str] = "default_theme",
width: int = 200,
height: int = 200,
font: any = "default_theme",
**kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
@ -41,7 +43,7 @@ class CTkTextbox(CTkBaseClass):
self._border_width = ThemeManager.theme["shape"]["frame_border_width"] if border_width == "default_theme" else border_width
# text
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
# configure 1x1 grid
self.grid_rowconfigure(0, weight=1)
@ -61,7 +63,7 @@ class CTkTextbox(CTkBaseClass):
fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
width=0,
height=0,
font=self._text_font,
font=self._font,
highlightthickness=0,
relief="flat",
insertbackground=ThemeManager.single_color(("black", "white"), self._appearance_mode),
@ -75,7 +77,7 @@ class CTkTextbox(CTkBaseClass):
def _set_scaling(self, *args, **kwargs):
super()._set_scaling(*args, **kwargs)
self._textbox.configure(font=self._apply_font_scaling(self.text_font))
self._textbox.configure(font=self._apply_font_scaling(self._font))
self._canvas.configure(width=self._apply_widget_scaling(self._desired_width),
height=self._apply_widget_scaling(self._desired_height))
self._draw()
@ -147,9 +149,9 @@ class CTkTextbox(CTkBaseClass):
if "height" in kwargs:
self._set_dimensions(height=kwargs.pop("height"))
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self._textbox.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
self._textbox.configure(font=self._apply_font_scaling(self._font))
if "font" in kwargs:
raise ValueError("No attribute named font. Use text_font instead of font for CTk widgets")
@ -161,6 +163,24 @@ class CTkTextbox(CTkBaseClass):
self._textbox.configure(**kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "corner_radius":
return self._corner_radius
elif attribute_name == "border_width":
return self._border_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "border_color":
return self._border_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "font":
return self._font
else:
return super().cget(attribute_name)
def yview(self, *args):
return self._textbox.yview(*args)

View File

@ -12,13 +12,16 @@ from ..scaling_tracker import ScalingTracker
class DropdownMenu(tkinter.Menu):
def __init__(self, *args,
min_character_width: int = 18,
fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_color: Union[str, Tuple[str, str]] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "default_theme",
text_font: Union[str, Tuple[str, str]] = "default_theme",
font: Union[str, Tuple[str, str]] = "default_theme",
command: Callable = None,
values: List[str] = None,
**kwargs):
super().__init__(*args, **kwargs)
ScalingTracker.add_widget(self._set_scaling, self)
@ -32,7 +35,7 @@ class DropdownMenu(tkinter.Menu):
self._fg_color = ThemeManager.theme["color"]["dropdown_color"] if fg_color == "default_theme" else fg_color
self._hover_color = ThemeManager.theme["color"]["dropdown_hover"] if hover_color == "default_theme" else hover_color
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self._text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
self._configure_menu_for_platforms()
@ -46,7 +49,7 @@ class DropdownMenu(tkinter.Menu):
if sys.platform == "darwin":
self.configure(tearoff=False,
font=self._apply_font_scaling(self._text_font))
font=self._apply_font_scaling(self._font))
elif sys.platform.startswith("win"):
self.configure(tearoff=False,
@ -57,7 +60,7 @@ class DropdownMenu(tkinter.Menu):
bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
activeforeground=ThemeManager.single_color(self._text_color, self._appearance_mode),
font=self._apply_font_scaling(self._text_font),
font=self._apply_font_scaling(self._font),
cursor="hand2")
else:
@ -69,7 +72,7 @@ class DropdownMenu(tkinter.Menu):
bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
activeforeground=ThemeManager.single_color(self._text_color, self._appearance_mode),
font=self._apply_font_scaling(self._text_font))
font=self._apply_font_scaling(self._font))
def _add_menu_commands(self):
""" delete existing menu labels and createe new labels with command according to values list """
@ -102,14 +105,10 @@ class DropdownMenu(tkinter.Menu):
else: # Linux
self.tk_popup(int(x), int(y))
def config(self, *args, **kwargs):
return self.configure(*args, **kwargs)
def config(self, **kwargs):
return self.configure(**kwargs)
def configure(self, **kwargs):
if "values" in kwargs:
self._values = kwargs.pop("values")
self._add_menu_commands()
if "fg_color" in kwargs:
self._fg_color = kwargs.pop("fg_color")
self.configure(bg=ThemeManager.single_color(self._fg_color, self._appearance_mode))
@ -122,11 +121,34 @@ class DropdownMenu(tkinter.Menu):
self._text_color = kwargs.pop("text_color")
self.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode))
if "text_font" in kwargs:
self._text_font = kwargs.pop("text_font")
self.configure(font=self._apply_font_scaling(self._text_font))
if "font" in kwargs:
self._font = kwargs.pop("font")
super().configure(font=self._apply_font_scaling(self._font))
super().configure(**kwargs)
if "command" in kwargs:
self._command = kwargs.pop("command")
if "values" in kwargs:
self._values = kwargs.pop("values")
self._add_menu_commands()
def cget(self, attribute_name: str) -> any:
if attribute_name == "min_character_width":
return self._min_character_width
elif attribute_name == "fg_color":
return self._fg_color
elif attribute_name == "hover_color":
return self._hover_color
elif attribute_name == "text_color":
return self._text_color
elif attribute_name == "font":
return self._font
elif attribute_name == "command":
return self._command
elif attribute_name == "values":
return self._values
def _apply_widget_scaling(self, value: Union[int, float, str]) -> Union[float, str]:
if isinstance(value, (int, float)):
@ -160,7 +182,7 @@ class DropdownMenu(tkinter.Menu):
self._widget_scaling = new_widget_scaling
self._spacing_scaling = new_spacing_scaling
self.configure(font=self._apply_font_scaling(self._text_font))
super().configure(font=self._apply_font_scaling(self._font))
if sys.platform.startswith("win"):
self.configure(activeborderwidth=self._apply_widget_scaling(4))

View File

@ -15,16 +15,21 @@ from ..appearance_mode_tracker import AppearanceModeTracker
from ..scaling_tracker import ScalingTracker
from ..theme_manager import ThemeManager
from .widget_helper_functions import filter_dict_by_set
class CTkBaseClass(tkinter.Frame):
""" Base class of every CTk widget, handles the dimensions, _bg_color,
appearance_mode changes, scaling, bg changes of master if master is not a CTk widget """
def __init__(self,
*args,
bg_color: Union[str, tuple] = None,
# attributes that are passed to and managed by the tkinter frame only:
_valid_tk_frame_attributes = {"cursor"}
def __init__(self, *args,
width: int,
height: int,
bg_color: Union[str, tuple] = None,
**kwargs):
super().__init__(*args, width=width, height=height, **kwargs) # set desired size of underlying tkinter.Frame
@ -117,6 +122,10 @@ class CTkBaseClass(tkinter.Frame):
return scaled_kwargs
def _draw(self, no_color_updates: bool = False):
""" abstract of draw method to be overridden """
pass
def config(self, *args, **kwargs):
return self.configure(*args, **kwargs)
@ -131,7 +140,7 @@ class CTkBaseClass(tkinter.Frame):
self._bg_color = new_bg_color
require_redraw = True
super().configure(**kwargs)
super().configure(**filter_dict_by_set(kwargs, self._valid_tk_frame_attributes))
if require_redraw:
self._draw()
@ -143,7 +152,8 @@ class CTkBaseClass(tkinter.Frame):
return self._desired_width
elif key == "height":
return self._desired_height
else:
elif key in self._valid_tk_frame_attributes:
return super().cget(key)
def _update_dimensions_event(self, event):
@ -241,7 +251,3 @@ class CTkBaseClass(tkinter.Frame):
else:
return font
def _draw(self, no_color_updates: bool = False):
""" abstract of draw method to be overridden """
pass

View File

@ -0,0 +1,11 @@
def filter_dict_by_set(dictionary: dict, valid_keys: set):
""" remove all key value pairs, where key is not in valid_keys set """
new_dictionary = {}
for key, value in dictionary.items():
if key in valid_keys:
new_dictionary[key] = value
return new_dictionary

View File

@ -18,12 +18,13 @@ class CTkInputDialog:
"""
def __init__(self,
master: any = None,
title: str = "CTkDialog",
text: str = "CTkDialog",
fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_color: Union[str, Tuple[str, str]] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "default_theme"):
border_color: Union[str, Tuple[str, str]] = "default_theme",
master: any = None,
title: str = "CTkDialog",
text: str = "CTkDialog"):
self._appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.master = master

View File

@ -263,6 +263,12 @@ class CTk(tkinter.Tk):
super().configure(*args, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "fg_color":
return self._fg_color
else:
return super().cget(attribute_name)
@staticmethod
def _enable_macos_dark_title_bar():
if sys.platform == "darwin" and not Settings.deactivate_macos_window_header_manipulation: # macOS

View File

@ -227,6 +227,12 @@ class CTkToplevel(tkinter.Toplevel):
super().configure(*args, **kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "fg_color":
return self._fg_color
else:
return super().cget(attribute_name)
@staticmethod
def _enable_macos_dark_title_bar():
if sys.platform == "darwin" and not Settings.deactivate_macos_window_header_manipulation: # macOS

View File

@ -42,7 +42,7 @@ class App(customtkinter.CTk):
self.label_1 = customtkinter.CTkLabel(master=self.frame_left,
text="CustomTkinter",
text_font=("Roboto Medium", -16)) # font name and size in px
font=("Roboto Medium", -16)) # font name and size in px
self.label_1.grid(row=1, column=0, pady=10, padx=10)
self.button_1 = customtkinter.CTkButton(master=self.frame_left,

View File

@ -24,7 +24,7 @@ class App(customtkinter.CTk):
self.sidebar_frame = customtkinter.CTkFrame(self, width=140)
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CustomTkinter", text_font=("Roboto", -16))
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CustomTkinter", font=("Roboto", -16))
self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))
self.sidebar_button_1 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_callback)
self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10)
@ -103,9 +103,9 @@ class App(customtkinter.CTk):
self.progressbar_2.grid(row=1, column=0, padx=(20, 10), pady=(10, 10), sticky="ew")
self.slider_1 = customtkinter.CTkSlider(self.slider_progressbar_frame, from_=0, to=1, number_of_steps=4)
self.slider_1.grid(row=2, column=0, padx=(20, 10), pady=(10, 10), sticky="ew")
self.slider_2 = customtkinter.CTkSlider(self.slider_progressbar_frame, orient="vertical")
self.slider_2 = customtkinter.CTkSlider(self.slider_progressbar_frame, orientation="vertical")
self.slider_2.grid(row=0, column=1, rowspan=4, padx=(10, 10), pady=(10, 10), sticky="ns")
self.progressbar_3 = customtkinter.CTkProgressBar(self.slider_progressbar_frame, orient="vertical")
self.progressbar_3 = customtkinter.CTkProgressBar(self.slider_progressbar_frame, orientation="vertical")
self.progressbar_3.grid(row=0, column=2, rowspan=4, padx=(10, 20), pady=(10, 10), sticky="ns")
# set default values