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/), 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). 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 ## [4.6.0] - 2022-09-17
### Added ### Added
- CTkProgressBar indeterminate mode, automatic progress loop with .start() and .stop() - CTkProgressBar indeterminate mode, automatic progress loop with .start() and .stop()

View File

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

View File

@ -16,26 +16,28 @@ class CTkCheckBox(CTkBaseClass):
""" """
def __init__(self, *args, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme", fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_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",
border_width: Union[int, str] = "default_theme",
checkmark_color: Union[str, Tuple[str, 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_color: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkCheckBox",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme", 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, hover: bool = True,
command: Callable = None, command: Callable = None,
state: str = tkinter.NORMAL,
onvalue: Union[int, str] = 1, onvalue: Union[int, str] = 1,
offvalue: Union[int, str] = 0, offvalue: Union[int, str] = 0,
variable: tkinter.Variable = None, variable: tkinter.Variable = None,
textvariable: tkinter.Variable = None,
**kwargs): **kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass # 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_label: Union[tkinter.Label, None] = None
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color 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_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 # callback and hover functionality
self._command = command self._command = command
@ -98,7 +100,7 @@ class CTkCheckBox(CTkBaseClass):
bd=0, bd=0,
text=self._text, text=self._text,
justify=tkinter.LEFT, justify=tkinter.LEFT,
font=self._apply_font_scaling(self._text_font), font=self._apply_font_scaling(self._font),
textvariable=self._textvariable) textvariable=self._textvariable)
self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w")
self._text_label["anchor"] = "w" self._text_label["anchor"] = "w"
@ -119,7 +121,7 @@ class CTkCheckBox(CTkBaseClass):
super()._set_scaling(*args, **kwargs) super()._set_scaling(*args, **kwargs)
self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6)) 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._canvas.delete("checkmark")
self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) 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 = kwargs.pop("text")
self._text_label.configure(text=self._text) self._text_label.configure(text=self._text)
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
if self._text_label is not None: 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: if "state" in kwargs:
self._state = kwargs.pop("state") self._state = kwargs.pop("state")
@ -229,6 +231,44 @@ class CTkCheckBox(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs) 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): def _set_cursor(self):
if Settings.cursor_manipulation_enabled: if Settings.cursor_manipulation_enabled:
if self._state == tkinter.DISABLED: if self._state == tkinter.DISABLED:

View File

@ -9,6 +9,8 @@ from ..settings import Settings
from ..draw_engine import DrawEngine from ..draw_engine import DrawEngine
from .widget_base_class import CTkBaseClass from .widget_base_class import CTkBaseClass
from .widget_helper_functions import filter_dict_by_set
class CTkComboBox(CTkBaseClass): class CTkComboBox(CTkBaseClass):
""" """
@ -17,27 +19,29 @@ class CTkComboBox(CTkBaseClass):
""" """
def __init__(self, *args, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme", fg_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",
button_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", 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_hover_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_text_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: Union[str, Tuple[str, str]] = "default_theme",
text_color_disabled: 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, state: str = tkinter.NORMAL,
hover: bool = True,
variable: tkinter.Variable = None,
command: Callable = None,
**kwargs): **kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass # transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass
@ -56,11 +60,11 @@ class CTkComboBox(CTkBaseClass):
# text and font # text and font
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color 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_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 # callback and hover functionality
self._command = command self._command = command
self._textvariable = variable self._variable = variable
self._state = state self._state = state
self._hover = hover self._hover = hover
@ -72,10 +76,10 @@ class CTkComboBox(CTkBaseClass):
self._dropdown_menu = DropdownMenu(master=self, self._dropdown_menu = DropdownMenu(master=self,
values=self._values, values=self._values,
command=self._dropdown_callback, command=self._dropdown_callback,
fg_color=dropdown_color, fg_color=dropdown_fg_color,
hover_color=dropdown_hover_color, hover_color=dropdown_hover_color,
text_color=dropdown_text_color, text_color=dropdown_text_color,
text_font=dropdown_text_font) font=dropdown_text_font)
# configure grid system (1x1) # configure grid system (1x1)
self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1)
@ -93,7 +97,7 @@ class CTkComboBox(CTkBaseClass):
width=1, width=1,
bd=0, bd=0,
highlightthickness=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 left_section_width = self._current_width - self._current_height
self._entry.grid(row=0, column=0, rowspan=1, columnspan=1, sticky="ew", 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)), 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._canvas.tag_bind("dropdown_arrow", "<Button-1>", self._clicked)
self.bind('<Configure>', self._update_dimensions_event) self.bind('<Configure>', self._update_dimensions_event)
if self._textvariable is not None: if self._variable is not None:
self._entry.configure(textvariable=self._textvariable) self._entry.configure(textvariable=self._variable)
def _set_scaling(self, *args, **kwargs): def _set_scaling(self, *args, **kwargs):
super()._set_scaling(*args, **kwargs) super()._set_scaling(*args, **kwargs)
# change entry font size and grid padding # change entry font size and grid padding
left_section_width = self._current_width - self._current_height 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", 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)), 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)))) 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") self._text_color = kwargs.pop("text_color")
require_redraw = True require_redraw = True
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
self._entry.configure(font=self._apply_font_scaling(self._text_font)) self._entry.configure(font=self._apply_font_scaling(self._font))
if "command" in kwargs: if "command" in kwargs:
self._command = kwargs.pop("command") self._command = kwargs.pop("command")
if "variable" in kwargs: if "variable" in kwargs:
self._textvariable = kwargs.pop("variable") self._variable = kwargs.pop("variable")
self._entry.configure(textvariable=self._textvariable) self._entry.configure(textvariable=self._variable)
if "width" in kwargs: if "width" in kwargs:
self._set_dimensions(width=kwargs.pop("width")) self._set_dimensions(width=kwargs.pop("width"))
@ -231,8 +235,8 @@ class CTkComboBox(CTkBaseClass):
self._values = kwargs.pop("values") self._values = kwargs.pop("values")
self._dropdown_menu.configure(values=self._values) self._dropdown_menu.configure(values=self._values)
if "dropdown_color" in kwargs: if "dropdown_fg_color" in kwargs:
self._dropdown_menu.configure(fg_color=kwargs.pop("dropdown_color")) self._dropdown_menu.configure(fg_color=kwargs.pop("dropdown_fg_color"))
if "dropdown_hover_color" in kwargs: if "dropdown_hover_color" in kwargs:
self._dropdown_menu.configure(hover_color=kwargs.pop("dropdown_hover_color")) 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) 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): def _on_enter(self, event=0):
if self._hover is True and self._state == tkinter.NORMAL and len(self._values) > 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: 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 ..draw_engine import DrawEngine
from .widget_base_class import CTkBaseClass from .widget_base_class import CTkBaseClass
from .widget_helper_functions import *
class CTkEntry(CTkBaseClass): class CTkEntry(CTkBaseClass):
""" """
@ -13,23 +15,33 @@ class CTkEntry(CTkBaseClass):
For detailed information check out the documentation. 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, 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, width: int = 140,
height: int = 28, 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, textvariable: tkinter.Variable = None,
placeholder_text: str = None,
font: Union[str, Tuple[str, str]] = "default_theme",
state: str = tkinter.NORMAL,
**kwargs): **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: if "master" in kwargs:
super().__init__(*args, bg_color=bg_color, width=width, height=height, master=kwargs.pop("master")) super().__init__(*args, bg_color=bg_color, width=width, height=height, master=kwargs.pop("master"))
else: else:
@ -43,7 +55,7 @@ class CTkEntry(CTkBaseClass):
self._fg_color = ThemeManager.theme["color"]["entry"] if fg_color == "default_theme" else fg_color 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._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._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 self._border_color = ThemeManager.theme["color"]["entry_border"] if border_color == "default_theme" else border_color
# shape # shape
@ -71,10 +83,10 @@ class CTkEntry(CTkBaseClass):
bd=0, bd=0,
width=1, width=1,
highlightthickness=0, highlightthickness=0,
font=self._apply_font_scaling(self._text_font), font=self._apply_font_scaling(self._font),
state=self._state, state=self._state,
textvariable=self._textvariable, textvariable=self._textvariable,
**kwargs) **filter_dict_by_set(kwargs, self._valid_tk_entry_attributes))
self._entry.grid(column=0, row=0, sticky="nswe", 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), 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))) 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): def _set_scaling(self, *args, **kwargs):
super()._set_scaling(*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", 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)) 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) return self.configure(*args, **kwargs)
def configure(self, require_redraw=False, **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: if "state" in kwargs:
self._state = kwargs.pop("state") self._state = kwargs.pop("state")
self._entry.configure(state=self._state) self._entry.configure(state=self._state)
@ -193,9 +207,9 @@ class CTkEntry(CTkBaseClass):
self._textvariable = kwargs.pop("textvariable") self._textvariable = kwargs.pop("textvariable")
self._entry.configure(textvariable=self._textvariable) self._entry.configure(textvariable=self._textvariable)
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
self._entry.configure(font=self._apply_font_scaling(self._text_font)) self._entry.configure(font=self._apply_font_scaling(self._font))
if "show" in kwargs: if "show" in kwargs:
if self._placeholder_text_active: if self._placeholder_text_active:
@ -203,12 +217,40 @@ class CTkEntry(CTkBaseClass):
else: else:
self._entry.configure(show=kwargs.pop("show")) self._entry.configure(show=kwargs.pop("show"))
if "_bg_color" in kwargs: super().configure(require_redraw=require_redraw, **kwargs)
super().configure(bg_color=kwargs.pop("_bg_color"), require_redraw=require_redraw)
else:
super().configure(require_redraw=require_redraw)
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): def bind(self, *args, **kwargs):
self._entry.bind(*args, **kwargs) self._entry.bind(*args, **kwargs)

View File

@ -15,13 +15,15 @@ class CTkFrame(CTkBaseClass):
""" """
def __init__(self, *args, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme", fg_color: Union[str, Tuple[str, str], None] = "default_theme",
border_color: Union[str, Tuple[str, str]] = "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, overwrite_preferred_drawing_method: str = None,
**kwargs): **kwargs):
@ -144,3 +146,16 @@ class CTkFrame(CTkBaseClass):
self._set_dimensions(height=kwargs.pop("height")) self._set_dimensions(height=kwargs.pop("height"))
super().configure(require_redraw=require_redraw, **kwargs) 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. 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, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme", fg_color: Union[str, Tuple[str, str], None] = "default_theme",
text_color: Union[str, Tuple[str, str]] = "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: str = "CTkLabel",
text_font: any = "default_theme", font: any = "default_theme",
anchor: str = "center", # label anchor: center, n, e, s, w anchor: str = "center", # label anchor: center, n, e, s, w
**kwargs): **kwargs):
@ -41,7 +46,7 @@ class CTkLabel(CTkBaseClass):
# text # text
self._anchor = anchor self._anchor = anchor
self._text = text 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) # configure grid system (1x1)
self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1)
@ -59,7 +64,7 @@ class CTkLabel(CTkBaseClass):
bd=0, bd=0,
anchor=self._anchor, anchor=self._anchor,
text=self._text, text=self._text,
font=self._apply_font_scaling(self._text_font), font=self._apply_font_scaling(self._font),
**kwargs) **kwargs)
text_label_grid_sticky = self._anchor if self._anchor != "center" else "" 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), 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) 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._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 "" 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), self._text_label.grid(row=0, column=0, padx=self._apply_widget_scaling(self._corner_radius),
sticky=text_label_grid_sticky) sticky=text_label_grid_sticky)
@ -124,9 +129,9 @@ class CTkLabel(CTkBaseClass):
self._text = kwargs.pop("text") self._text = kwargs.pop("text")
self._text_label.configure(text=self._text) self._text_label.configure(text=self._text)
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
self._text_label.configure(font=self._apply_font_scaling(self._text_font)) self._text_label.configure(font=self._apply_font_scaling(self._font))
if "fg_color" in kwargs: if "fg_color" in kwargs:
self._fg_color = kwargs.pop("fg_color") self._fg_color = kwargs.pop("fg_color")
@ -148,3 +153,21 @@ class CTkLabel(CTkBaseClass):
super().configure(require_redraw=require_redraw) super().configure(require_redraw=require_redraw)
self._text_label.configure(**kwargs) # pass remaining kwargs to label 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): 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. For detailed information check out the documentation.
""" """
def __init__(self, *args, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme", fg_color: Union[str, Tuple[str, str]] = "default_theme",
button_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", button_hover_color: Union[str, Tuple[str, str]] = "default_theme",
text_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_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_hover_color: Union[str, Tuple[str, str]] = "default_theme",
dropdown_text_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, font: any = "default_theme",
command: Callable = None,
width: int = 140,
height: int = 28,
corner_radius: Union[int, str] = "default_theme",
text_font: any = "default_theme",
dropdown_text_font: any = "default_theme", dropdown_text_font: any = "default_theme",
hover: bool = True, values: list = None,
variable: tkinter.Variable = None,
state: str = tkinter.NORMAL, state: str = tkinter.NORMAL,
hover: bool = True,
command: Callable = None,
dynamic_resizing: bool = True, dynamic_resizing: bool = True,
**kwargs): **kwargs):
@ -53,7 +55,7 @@ class CTkOptionMenu(CTkBaseClass):
# text and font # text and font
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color 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_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 self._dropdown_text_font = dropdown_text_font
# callback and hover functionality # callback and hover functionality
@ -78,10 +80,10 @@ class CTkOptionMenu(CTkBaseClass):
self._dropdown_menu = DropdownMenu(master=self, self._dropdown_menu = DropdownMenu(master=self,
values=self._values, values=self._values,
command=self._dropdown_callback, command=self._dropdown_callback,
fg_color=dropdown_color, fg_color=dropdown_fg_color,
hover_color=dropdown_hover_color, hover_color=dropdown_hover_color,
text_color=dropdown_text_color, text_color=dropdown_text_color,
text_font=dropdown_text_font) font=dropdown_text_font)
# configure grid system (1x1) # configure grid system (1x1)
self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1)
@ -96,7 +98,7 @@ class CTkOptionMenu(CTkBaseClass):
left_section_width = self._current_width - self._current_height left_section_width = self._current_width - self._current_height
self._text_label = tkinter.Label(master=self, self._text_label = tkinter.Label(master=self,
font=self._apply_font_scaling(self._text_font), font=self._apply_font_scaling(self._font),
anchor="w", anchor="w",
text=self._current_value) text=self._current_value)
self._text_label.grid(row=0, column=0, sticky="w", self._text_label.grid(row=0, column=0, sticky="w",
@ -137,7 +139,7 @@ class CTkOptionMenu(CTkBaseClass):
# change label text size and grid padding # change label text size and grid padding
left_section_width = self._current_width - self._current_height 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", self._text_label.grid(row=0, column=0, sticky="w",
padx=(max(self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(3)), 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)))) 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") self._text_color = kwargs.pop("text_color")
require_redraw = True require_redraw = True
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
self._text_label.configure(font=self._apply_font_scaling(self._text_font)) self._text_label.configure(font=self._apply_font_scaling(self._font))
if "command" in kwargs: if "command" in kwargs:
self._command = kwargs.pop("command") self._command = kwargs.pop("command")
@ -267,6 +269,46 @@ class CTkOptionMenu(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs) 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): def _open_dropdown_menu(self):
self._dropdown_menu.open(self.winfo_rootx(), self._dropdown_menu.open(self.winfo_rootx(),
self.winfo_rooty() + self._apply_widget_scaling(self._current_height + 0)) self.winfo_rooty() + self._apply_widget_scaling(self._current_height + 0))

View File

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

View File

@ -16,25 +16,27 @@ class CTkRadioButton(CTkBaseClass):
""" """
def __init__(self, *args, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str]] = "default_theme", fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_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",
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_color: Union[str, Tuple[str, str]] = "default_theme",
text: str = "CTkRadioButton",
text_color_disabled: Union[str, Tuple[str, str]] = "default_theme", 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, hover: bool = True,
command: Callable = None, command: Callable = None,
state: str = tkinter.NORMAL,
value: Union[int, str] = 0,
variable: tkinter.Variable = None,
textvariable: tkinter.Variable = None,
**kwargs): **kwargs):
# transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass # 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_label: Union[tkinter.Label, None] = None
self._text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color 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_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 # callback and control variables
self._command = command self._command = command
@ -95,7 +97,7 @@ class CTkRadioButton(CTkBaseClass):
bd=0, bd=0,
text=self._text, text=self._text,
justify=tkinter.LEFT, justify=tkinter.LEFT,
font=self._apply_font_scaling(self._text_font), font=self._apply_font_scaling(self._font),
textvariable=self._textvariable) textvariable=self._textvariable)
self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w")
self._text_label["anchor"] = "w" self._text_label["anchor"] = "w"
@ -115,7 +117,7 @@ class CTkRadioButton(CTkBaseClass):
super()._set_scaling(*args, **kwargs) super()._set_scaling(*args, **kwargs)
self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6)) 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._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)) 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 = kwargs.pop("text")
self._text_label.configure(text=self._text) self._text_label.configure(text=self._text)
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
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: if "state" in kwargs:
self._state = kwargs.pop("state") self._state = kwargs.pop("state")
@ -213,6 +215,44 @@ class CTkRadioButton(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs) 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): def _set_cursor(self):
if Settings.cursor_manipulation_enabled: if Settings.cursor_manipulation_enabled:
if self._state == tkinter.DISABLED: if self._state == tkinter.DISABLED:

View File

@ -15,18 +15,20 @@ class CTkScrollbar(CTkBaseClass):
""" """
def __init__(self, *args, 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, bg_color: Union[str, Tuple[str, str], None] = None,
fg_color: Union[str, Tuple[str, str], None] = "default_theme", fg_color: Union[str, Tuple[str, str], None] = "default_theme",
scrollbar_color: Union[str, Tuple[str, str]] = "default_theme", scrollbar_color: Union[str, Tuple[str, str]] = "default_theme",
scrollbar_hover_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, hover: bool = True,
command: Callable = None,
orientation: str = "vertical",
**kwargs): **kwargs):
# set default dimensions according to orientation # set default dimensions according to orientation
@ -183,6 +185,30 @@ class CTkScrollbar(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs) 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): def _on_enter(self, event=0):
if self._hover is True: if self._hover is True:
self._hover_state = True self._hover_state = True

View File

@ -16,35 +16,37 @@ class CTkSlider(CTkBaseClass):
""" """
def __init__(self, *args, 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", width: Union[int, str] = "default_init",
height: Union[int, str] = "default_init", height: Union[int, str] = "default_init",
corner_radius: Union[int, str] = "default_theme", corner_radius: Union[int, str] = "default_theme",
button_corner_radius: Union[int, str] = "default_theme", button_corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme", border_width: Union[int, str] = "default_theme",
button_length: 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, command: Callable = None,
variable: tkinter.Variable = None, variable: tkinter.Variable = None,
orient: str = "horizontal", orientation: str = "horizontal",
state: str = "normal",
**kwargs): **kwargs):
# set default dimensions according to orientation # set default dimensions according to orientation
if width == "default_init": if width == "default_init":
if orient.lower() == "vertical": if orientation.lower() == "vertical":
width = 16 width = 16
else: else:
width = 200 width = 200
if height == "default_init": if height == "default_init":
if orient.lower() == "vertical": if orientation.lower() == "vertical":
height = 200 height = 200
else: else:
height = 16 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._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._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._value: float = 0.5 # initial value of slider in percent
self._orientation = orient self._orientation = orientation
self._hover_state: bool = False self._hover_state: bool = False
self._from_ = from_ self._from_ = from_
self._to = to self._to = to
@ -253,6 +255,44 @@ class CTkSlider(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs) 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): def _clicked(self, event=None):
if self._state == "normal": if self._state == "normal":
if self._orientation.lower() == "horizontal": if self._orientation.lower() == "horizontal":

View File

@ -16,26 +16,28 @@ class CTkSwitch(CTkBaseClass):
""" """
def __init__(self, *args, 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, width: int = 36,
height: int = 18, 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", corner_radius: Union[int, str] = "default_theme",
border_width: Union[int, str] = "default_theme", border_width: Union[int, str] = "default_theme",
button_length: 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, onvalue: Union[int, str] = 1,
offvalue: Union[int, str] = 0, offvalue: Union[int, str] = 0,
variable: tkinter.Variable = None, variable: tkinter.Variable = None,
textvariable: tkinter.Variable = None, command: Callable = None,
state: str = tkinter.NORMAL, state: str = tkinter.NORMAL,
**kwargs): **kwargs):
@ -54,7 +56,7 @@ class CTkSwitch(CTkBaseClass):
# text # text
self._text = text self._text = text
self._text_label = None 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 # shape
self._corner_radius = ThemeManager.theme["shape"]["switch_corner_radius"] if corner_radius == "default_theme" else corner_radius 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, bd=0,
text=self._text, text=self._text,
justify=tkinter.LEFT, justify=tkinter.LEFT,
font=self._apply_font_scaling(self._text_font), font=self._apply_font_scaling(self._font),
textvariable=self._textvariable) textvariable=self._textvariable)
self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w")
self._text_label["anchor"] = "w" self._text_label["anchor"] = "w"
@ -120,7 +122,7 @@ class CTkSwitch(CTkBaseClass):
super()._set_scaling(*args, **kwargs) super()._set_scaling(*args, **kwargs)
self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6)) 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._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)) 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 = kwargs.pop("text")
self._text_label.configure(text=self._text) self._text_label.configure(text=self._text)
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
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: if "state" in kwargs:
self._state = kwargs.pop("state") self._state = kwargs.pop("state")
@ -270,6 +272,48 @@ class CTkSwitch(CTkBaseClass):
super().configure(require_redraw=require_redraw, **kwargs) 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): def toggle(self, event=None):
if self._state is not tkinter.DISABLED: if self._state is not tkinter.DISABLED:
if self._check_state is True: if self._check_state is True:

View File

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

View File

@ -12,13 +12,16 @@ from ..scaling_tracker import ScalingTracker
class DropdownMenu(tkinter.Menu): class DropdownMenu(tkinter.Menu):
def __init__(self, *args, def __init__(self, *args,
min_character_width: int = 18, min_character_width: int = 18,
fg_color: Union[str, Tuple[str, str]] = "default_theme", fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_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_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, command: Callable = None,
values: List[str] = None, values: List[str] = None,
**kwargs): **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
ScalingTracker.add_widget(self._set_scaling, self) 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._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._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_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() self._configure_menu_for_platforms()
@ -46,7 +49,7 @@ class DropdownMenu(tkinter.Menu):
if sys.platform == "darwin": if sys.platform == "darwin":
self.configure(tearoff=False, self.configure(tearoff=False,
font=self._apply_font_scaling(self._text_font)) font=self._apply_font_scaling(self._font))
elif sys.platform.startswith("win"): elif sys.platform.startswith("win"):
self.configure(tearoff=False, self.configure(tearoff=False,
@ -57,7 +60,7 @@ class DropdownMenu(tkinter.Menu):
bg=ThemeManager.single_color(self._fg_color, self._appearance_mode), bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
fg=ThemeManager.single_color(self._text_color, self._appearance_mode), fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
activeforeground=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") cursor="hand2")
else: else:
@ -69,7 +72,7 @@ class DropdownMenu(tkinter.Menu):
bg=ThemeManager.single_color(self._fg_color, self._appearance_mode), bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
fg=ThemeManager.single_color(self._text_color, self._appearance_mode), fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
activeforeground=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): def _add_menu_commands(self):
""" delete existing menu labels and createe new labels with command according to values list """ """ delete existing menu labels and createe new labels with command according to values list """
@ -102,14 +105,10 @@ class DropdownMenu(tkinter.Menu):
else: # Linux else: # Linux
self.tk_popup(int(x), int(y)) self.tk_popup(int(x), int(y))
def config(self, *args, **kwargs): def config(self, **kwargs):
return self.configure(*args, **kwargs) return self.configure(**kwargs)
def configure(self, **kwargs): def configure(self, **kwargs):
if "values" in kwargs:
self._values = kwargs.pop("values")
self._add_menu_commands()
if "fg_color" in kwargs: if "fg_color" in kwargs:
self._fg_color = kwargs.pop("fg_color") self._fg_color = kwargs.pop("fg_color")
self.configure(bg=ThemeManager.single_color(self._fg_color, self._appearance_mode)) 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._text_color = kwargs.pop("text_color")
self.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) self.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode))
if "text_font" in kwargs: if "font" in kwargs:
self._text_font = kwargs.pop("text_font") self._font = kwargs.pop("font")
self.configure(font=self._apply_font_scaling(self._text_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]: def _apply_widget_scaling(self, value: Union[int, float, str]) -> Union[float, str]:
if isinstance(value, (int, float)): if isinstance(value, (int, float)):
@ -160,7 +182,7 @@ class DropdownMenu(tkinter.Menu):
self._widget_scaling = new_widget_scaling self._widget_scaling = new_widget_scaling
self._spacing_scaling = new_spacing_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"): if sys.platform.startswith("win"):
self.configure(activeborderwidth=self._apply_widget_scaling(4)) 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 ..scaling_tracker import ScalingTracker
from ..theme_manager import ThemeManager from ..theme_manager import ThemeManager
from .widget_helper_functions import filter_dict_by_set
class CTkBaseClass(tkinter.Frame): class CTkBaseClass(tkinter.Frame):
""" Base class of every CTk widget, handles the dimensions, _bg_color, """ 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 """ appearance_mode changes, scaling, bg changes of master if master is not a CTk widget """
def __init__(self, # attributes that are passed to and managed by the tkinter frame only:
*args, _valid_tk_frame_attributes = {"cursor"}
bg_color: Union[str, tuple] = None,
def __init__(self, *args,
width: int, width: int,
height: int, height: int,
bg_color: Union[str, tuple] = None,
**kwargs): **kwargs):
super().__init__(*args, width=width, height=height, **kwargs) # set desired size of underlying tkinter.Frame 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 return scaled_kwargs
def _draw(self, no_color_updates: bool = False):
""" abstract of draw method to be overridden """
pass
def config(self, *args, **kwargs): def config(self, *args, **kwargs):
return self.configure(*args, **kwargs) return self.configure(*args, **kwargs)
@ -131,7 +140,7 @@ class CTkBaseClass(tkinter.Frame):
self._bg_color = new_bg_color self._bg_color = new_bg_color
require_redraw = True require_redraw = True
super().configure(**kwargs) super().configure(**filter_dict_by_set(kwargs, self._valid_tk_frame_attributes))
if require_redraw: if require_redraw:
self._draw() self._draw()
@ -143,7 +152,8 @@ class CTkBaseClass(tkinter.Frame):
return self._desired_width return self._desired_width
elif key == "height": elif key == "height":
return self._desired_height return self._desired_height
else:
elif key in self._valid_tk_frame_attributes:
return super().cget(key) return super().cget(key)
def _update_dimensions_event(self, event): def _update_dimensions_event(self, event):
@ -241,7 +251,3 @@ class CTkBaseClass(tkinter.Frame):
else: else:
return font 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, def __init__(self,
master: any = None,
title: str = "CTkDialog",
text: str = "CTkDialog",
fg_color: Union[str, Tuple[str, str]] = "default_theme", fg_color: Union[str, Tuple[str, str]] = "default_theme",
hover_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._appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.master = master self.master = master

View File

@ -263,6 +263,12 @@ class CTk(tkinter.Tk):
super().configure(*args, **kwargs) 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 @staticmethod
def _enable_macos_dark_title_bar(): def _enable_macos_dark_title_bar():
if sys.platform == "darwin" and not Settings.deactivate_macos_window_header_manipulation: # macOS 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) 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 @staticmethod
def _enable_macos_dark_title_bar(): def _enable_macos_dark_title_bar():
if sys.platform == "darwin" and not Settings.deactivate_macos_window_header_manipulation: # macOS 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, self.label_1 = customtkinter.CTkLabel(master=self.frame_left,
text="CustomTkinter", 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.label_1.grid(row=1, column=0, pady=10, padx=10)
self.button_1 = customtkinter.CTkButton(master=self.frame_left, 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 = customtkinter.CTkFrame(self, width=140)
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew") self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1) 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.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 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_callback)
self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10) 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.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 = 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_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.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") self.progressbar_3.grid(row=0, column=2, rowspan=4, padx=(10, 20), pady=(10, 10), sticky="ns")
# set default values # set default values