mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
removed .config(), added kwargs managing and filtering, added kwargs exceptions, fixed cursor color for combobox
This commit is contained in:
parent
bfc42c25ef
commit
1374e04f04
@ -4,6 +4,13 @@ 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).
|
||||||
|
|
||||||
|
ToDo:
|
||||||
|
- limit configuring attributes of overridden tk widgets
|
||||||
|
- remove bg and background support for CTk and CTkToplevel (to be done)
|
||||||
|
- optimize font attribute managing
|
||||||
|
- enforce font size in pixel
|
||||||
|
- enforce font to be tuple
|
||||||
|
|
||||||
## Unreleased - 2022-10-2
|
## Unreleased - 2022-10-2
|
||||||
### Added
|
### Added
|
||||||
- added .cget() method to all widgets and windows
|
- added .cget() method to all widgets and windows
|
||||||
|
@ -240,9 +240,6 @@ class CTkButton(CTkBaseClass):
|
|||||||
padx=max(self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(self._border_width)),
|
padx=max(self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(self._border_width)),
|
||||||
pady=(self._apply_widget_scaling(self._border_width), 2))
|
pady=(self._apply_widget_scaling(self._border_width), 2))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "text" in kwargs:
|
if "text" in kwargs:
|
||||||
self._text = kwargs.pop("text")
|
self._text = kwargs.pop("text")
|
||||||
|
@ -177,9 +177,6 @@ class CTkCheckBox(CTkBaseClass):
|
|||||||
|
|
||||||
self._text_label.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
self._text_label.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "text" in kwargs:
|
if "text" in kwargs:
|
||||||
self._text = kwargs.pop("text")
|
self._text = kwargs.pop("text")
|
||||||
|
@ -175,8 +175,10 @@ class CTkComboBox(CTkBaseClass):
|
|||||||
|
|
||||||
self._entry.configure(bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
self._entry.configure(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),
|
||||||
|
disabledbackground=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
||||||
disabledforeground=ThemeManager.single_color(self._text_color_disabled, self._appearance_mode),
|
disabledforeground=ThemeManager.single_color(self._text_color_disabled, self._appearance_mode),
|
||||||
disabledbackground=ThemeManager.single_color(self._fg_color, self._appearance_mode))
|
highlightcolor=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
||||||
|
insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
||||||
|
|
||||||
if self._state == tkinter.DISABLED:
|
if self._state == tkinter.DISABLED:
|
||||||
self._canvas.itemconfig("dropdown_arrow",
|
self._canvas.itemconfig("dropdown_arrow",
|
||||||
@ -189,9 +191,6 @@ class CTkComboBox(CTkBaseClass):
|
|||||||
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))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "state" in kwargs:
|
if "state" in kwargs:
|
||||||
self._state = kwargs.pop("state")
|
self._state = kwargs.pop("state")
|
||||||
|
@ -6,7 +6,7 @@ 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 *
|
from .widget_helper_functions import pop_from_dict_by_set
|
||||||
|
|
||||||
|
|
||||||
class CTkEntry(CTkBaseClass):
|
class CTkEntry(CTkBaseClass):
|
||||||
@ -15,13 +15,12 @@ class CTkEntry(CTkBaseClass):
|
|||||||
For detailed information check out the documentation.
|
For detailed information check out the documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_minimum_x_padding = 6 # minimum padding between tkinter entry and frame border
|
||||||
|
|
||||||
# attributes that are passed to and managed by the tkinter entry only:
|
# attributes that are passed to and managed by the tkinter entry only:
|
||||||
_valid_tk_entry_attributes = {"exportselection", "font", "highlightbackground",
|
_valid_tk_entry_attributes = {"exportselection", "insertborderwidth", "insertofftime",
|
||||||
"highlightcolor", "insertbackground", "insertborderwidth",
|
"insertontime", "insertwidth", "justify", "selectborderwidth",
|
||||||
"insertofftime", "insertontime", "insertwidth",
|
"show", "takefocus", "validate", "validatecommand", "xscrollcommand"}
|
||||||
"justify", "selectbackground", "selectborderwidth",
|
|
||||||
"selectforeground", "show", "takefocus", "validate",
|
|
||||||
"validatecommand", "xscrollcommand"}
|
|
||||||
|
|
||||||
def __init__(self, *args,
|
def __init__(self, *args,
|
||||||
width: int = 140,
|
width: int = 140,
|
||||||
@ -55,22 +54,24 @@ 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._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
|
||||||
self._corner_radius = ThemeManager.theme["shape"]["button_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
self._corner_radius = ThemeManager.theme["shape"]["button_corner_radius"] if corner_radius == "default_theme" else corner_radius
|
||||||
self._border_width = ThemeManager.theme["shape"]["entry_border_width"] if border_width == "default_theme" else border_width
|
self._border_width = ThemeManager.theme["shape"]["entry_border_width"] if border_width == "default_theme" else border_width
|
||||||
|
|
||||||
# placeholder text
|
# text and state
|
||||||
|
self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font
|
||||||
self._is_focused: bool = True
|
self._is_focused: bool = True
|
||||||
self._placeholder_text = placeholder_text
|
self._placeholder_text = placeholder_text
|
||||||
self._placeholder_text_active = False
|
self._placeholder_text_active = False
|
||||||
self._pre_placeholder_arguments = {} # some set arguments of the entry will be changed for placeholder and then set back
|
self._pre_placeholder_arguments = {} # some set arguments of the entry will be changed for placeholder and then set back
|
||||||
|
|
||||||
# textvariable
|
|
||||||
self._textvariable = textvariable
|
self._textvariable = textvariable
|
||||||
self._state = state
|
self._state = state
|
||||||
|
self._textvariable_callback_name: str = ""
|
||||||
|
|
||||||
|
if not (self._textvariable is None or self._textvariable is ""):
|
||||||
|
self._textvariable_callback_name = self._textvariable.trace_add("write", self._textvariable_callback)
|
||||||
|
|
||||||
self._canvas = CTkCanvas(master=self,
|
self._canvas = CTkCanvas(master=self,
|
||||||
highlightthickness=0,
|
highlightthickness=0,
|
||||||
@ -86,10 +87,15 @@ class CTkEntry(CTkBaseClass):
|
|||||||
font=self._apply_font_scaling(self._font),
|
font=self._apply_font_scaling(self._font),
|
||||||
state=self._state,
|
state=self._state,
|
||||||
textvariable=self._textvariable,
|
textvariable=self._textvariable,
|
||||||
**filter_dict_by_set(kwargs, self._valid_tk_entry_attributes))
|
**pop_from_dict_by_set(kwargs, self._valid_tk_entry_attributes))
|
||||||
self._entry.grid(column=0, row=0, sticky="nswe",
|
if self._corner_radius >= self._minimum_x_padding:
|
||||||
padx=self._apply_widget_scaling(self._corner_radius) if self._corner_radius >= 6 else self._apply_widget_scaling(6),
|
self._entry.grid(column=0, row=0, sticky="nswe", padx=min(self._apply_widget_scaling(self._corner_radius), self._current_height),
|
||||||
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)))
|
||||||
|
else:
|
||||||
|
self._entry.grid(column=0, row=0, sticky="nswe", padx=self._apply_widget_scaling(self._minimum_x_padding),
|
||||||
|
pady=(self._apply_widget_scaling(self._border_width), self._apply_widget_scaling(self._border_width + 1)))
|
||||||
|
|
||||||
|
self._check_kwargs_empty(kwargs, raise_error=True)
|
||||||
|
|
||||||
super().bind('<Configure>', self._update_dimensions_event)
|
super().bind('<Configure>', self._update_dimensions_event)
|
||||||
self._entry.bind('<FocusOut>', self._entry_focus_out)
|
self._entry.bind('<FocusOut>', self._entry_focus_out)
|
||||||
@ -98,6 +104,10 @@ class CTkEntry(CTkBaseClass):
|
|||||||
self._activate_placeholder()
|
self._activate_placeholder()
|
||||||
self._draw()
|
self._draw()
|
||||||
|
|
||||||
|
def _textvariable_callback(self, var_name, index, mode):
|
||||||
|
if self._textvariable.get() == "":
|
||||||
|
self._activate_placeholder()
|
||||||
|
|
||||||
def _set_scaling(self, *args, **kwargs):
|
def _set_scaling(self, *args, **kwargs):
|
||||||
super()._set_scaling(*args, **kwargs)
|
super()._set_scaling(*args, **kwargs)
|
||||||
|
|
||||||
@ -129,20 +139,20 @@ class CTkEntry(CTkBaseClass):
|
|||||||
fill=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
fill=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
||||||
outline=ThemeManager.single_color(self._fg_color, self._appearance_mode))
|
outline=ThemeManager.single_color(self._fg_color, self._appearance_mode))
|
||||||
self._entry.configure(bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
self._entry.configure(bg=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
||||||
disabledbackground=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
|
||||||
highlightcolor=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),
|
||||||
|
disabledbackground=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
||||||
disabledforeground=ThemeManager.single_color(self._text_color, self._appearance_mode),
|
disabledforeground=ThemeManager.single_color(self._text_color, self._appearance_mode),
|
||||||
|
highlightcolor=ThemeManager.single_color(self._fg_color, self._appearance_mode),
|
||||||
insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
||||||
else:
|
else:
|
||||||
self._canvas.itemconfig("inner_parts",
|
self._canvas.itemconfig("inner_parts",
|
||||||
fill=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
fill=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
||||||
outline=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
outline=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
||||||
self._entry.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
self._entry.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
||||||
disabledbackground=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
|
||||||
highlightcolor=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
|
||||||
fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
|
fg=ThemeManager.single_color(self._text_color, self._appearance_mode),
|
||||||
|
disabledbackground=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
||||||
disabledforeground=ThemeManager.single_color(self._text_color, self._appearance_mode),
|
disabledforeground=ThemeManager.single_color(self._text_color, self._appearance_mode),
|
||||||
|
highlightcolor=ThemeManager.single_color(self._bg_color, self._appearance_mode),
|
||||||
insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode))
|
||||||
|
|
||||||
self._canvas.itemconfig("border_parts",
|
self._canvas.itemconfig("border_parts",
|
||||||
@ -152,12 +162,7 @@ class CTkEntry(CTkBaseClass):
|
|||||||
if self._placeholder_text_active:
|
if self._placeholder_text_active:
|
||||||
self._entry.config(fg=ThemeManager.single_color(self._placeholder_text_color, self._appearance_mode))
|
self._entry.config(fg=ThemeManager.single_color(self._placeholder_text_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *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)
|
||||||
@ -174,15 +179,16 @@ class CTkEntry(CTkBaseClass):
|
|||||||
self._border_color = kwargs.pop("border_color")
|
self._border_color = kwargs.pop("border_color")
|
||||||
require_redraw = True
|
require_redraw = True
|
||||||
|
|
||||||
|
if "border_width" in kwargs:
|
||||||
|
self._border_width = kwargs.pop("border_width")
|
||||||
|
require_redraw = True
|
||||||
|
|
||||||
if "corner_radius" in kwargs:
|
if "corner_radius" in kwargs:
|
||||||
self._corner_radius = kwargs.pop("corner_radius")
|
self._corner_radius = kwargs.pop("corner_radius")
|
||||||
|
if self._corner_radius >= self._minimum_x_padding:
|
||||||
if self._corner_radius * 2 > self._current_height:
|
self._entry.grid(column=0, row=0, sticky="we", padx=min(self._apply_widget_scaling(self._corner_radius), self._current_height / 2))
|
||||||
self._corner_radius = self._current_height / 2
|
else:
|
||||||
elif self._corner_radius * 2 > self._current_width:
|
self._entry.grid(column=0, row=0, sticky="we", padx=self._apply_widget_scaling(self._minimum_x_padding))
|
||||||
self._corner_radius = self._current_width / 2
|
|
||||||
|
|
||||||
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))
|
|
||||||
require_redraw = True
|
require_redraw = True
|
||||||
|
|
||||||
if "width" in kwargs:
|
if "width" in kwargs:
|
||||||
@ -213,11 +219,12 @@ class CTkEntry(CTkBaseClass):
|
|||||||
|
|
||||||
if "show" in kwargs:
|
if "show" in kwargs:
|
||||||
if self._placeholder_text_active:
|
if self._placeholder_text_active:
|
||||||
self._pre_placeholder_arguments["show"] = kwargs.pop("show")
|
self._pre_placeholder_arguments["show"] = kwargs.pop("show") # remember show argument for when placeholder gets deactivated
|
||||||
else:
|
else:
|
||||||
self._entry.configure(show=kwargs.pop("show"))
|
self._entry.configure(show=kwargs.pop("show"))
|
||||||
|
|
||||||
super().configure(require_redraw=require_redraw, **kwargs)
|
self._entry.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_entry_attributes)) # configure Tkinter.Entry
|
||||||
|
super().configure(require_redraw=require_redraw, **kwargs) # configure CTkBaseClass
|
||||||
|
|
||||||
def cget(self, attribute_name: str) -> any:
|
def cget(self, attribute_name: str) -> any:
|
||||||
if attribute_name == "corner_radius":
|
if attribute_name == "corner_radius":
|
||||||
@ -238,22 +245,18 @@ class CTkEntry(CTkBaseClass):
|
|||||||
return self._textvariable
|
return self._textvariable
|
||||||
elif attribute_name == "placeholder_text":
|
elif attribute_name == "placeholder_text":
|
||||||
return self._placeholder_text
|
return self._placeholder_text
|
||||||
elif attribute_name == "text_font":
|
elif attribute_name == "font":
|
||||||
return self._font
|
return self._font
|
||||||
elif attribute_name == "state":
|
elif attribute_name == "state":
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
elif attribute_name in ["exportselection", "font", "highlightbackground",
|
elif attribute_name in self._valid_tk_entry_attributes:
|
||||||
"highlightcolor", "insertbackground",
|
return self._entry.cget(attribute_name) # cget of tkinter.Entry
|
||||||
"insertborderwidth", "insertofftime", "insertontime",
|
else:
|
||||||
"insertwidth", "justify", "selectbackground",
|
return super().cget(attribute_name)
|
||||||
"selectborderwidth", "selectforeground", "show",
|
|
||||||
"takefocus", "validate", "validatecommand",
|
|
||||||
"xscrollcommand"]:
|
|
||||||
return self._entry.cget(attribute_name)
|
|
||||||
|
|
||||||
def bind(self, *args, **kwargs):
|
def bind(self, sequence=None, command=None, add=None):
|
||||||
self._entry.bind(*args, **kwargs)
|
self._entry.bind(sequence, command, add)
|
||||||
|
|
||||||
def _activate_placeholder(self):
|
def _activate_placeholder(self):
|
||||||
if self._entry.get() == "" and self._placeholder_text is not None and (self._textvariable is None or self._textvariable == ""):
|
if self._entry.get() == "" and self._placeholder_text is not None and (self._textvariable is None or self._textvariable == ""):
|
||||||
@ -281,16 +284,16 @@ class CTkEntry(CTkBaseClass):
|
|||||||
self._deactivate_placeholder()
|
self._deactivate_placeholder()
|
||||||
self._is_focused = True
|
self._is_focused = True
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, first_index, last_index=None):
|
||||||
self._entry.delete(*args, **kwargs)
|
self._entry.delete(first_index, last_index)
|
||||||
|
|
||||||
if not self._is_focused and self._entry.get() == "":
|
if not self._is_focused and self._entry.get() == "":
|
||||||
self._activate_placeholder()
|
self._activate_placeholder()
|
||||||
|
|
||||||
def insert(self, *args, **kwargs):
|
def insert(self, index, string):
|
||||||
self._deactivate_placeholder()
|
self._deactivate_placeholder()
|
||||||
|
|
||||||
return self._entry.insert(*args, **kwargs)
|
return self._entry.insert(index, string)
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
if self._placeholder_text_active:
|
if self._placeholder_text_active:
|
||||||
@ -299,7 +302,40 @@ class CTkEntry(CTkBaseClass):
|
|||||||
return self._entry.get()
|
return self._entry.get()
|
||||||
|
|
||||||
def focus(self):
|
def focus(self):
|
||||||
self._entry.focus()
|
return self._entry.focus()
|
||||||
|
|
||||||
def focus_force(self):
|
def focus_force(self):
|
||||||
self._entry.focus_force()
|
return self._entry.focus_force()
|
||||||
|
|
||||||
|
def index(self, index):
|
||||||
|
return self._entry.index(index)
|
||||||
|
|
||||||
|
def icursor(self, index):
|
||||||
|
return self._entry.icursor(index)
|
||||||
|
|
||||||
|
def select_adjust(self, index):
|
||||||
|
return self._entry.select_adjust(index)
|
||||||
|
|
||||||
|
def select_from(self, index):
|
||||||
|
return self._entry.icursor(index)
|
||||||
|
|
||||||
|
def select_clear(self):
|
||||||
|
return self._entry.select_clear()
|
||||||
|
|
||||||
|
def select_present(self):
|
||||||
|
return self._entry.select_present()
|
||||||
|
|
||||||
|
def select_range(self, start_index, end_index):
|
||||||
|
return self._entry.select_range(start_index, end_index)
|
||||||
|
|
||||||
|
def select_to(self, index):
|
||||||
|
return self._entry.select_to(index)
|
||||||
|
|
||||||
|
def xview(self, index):
|
||||||
|
return self._entry.xview(index)
|
||||||
|
|
||||||
|
def xview_moveto(self, f):
|
||||||
|
return self._entry.xview_moveto(f)
|
||||||
|
|
||||||
|
def xview_scroll(self, number, what):
|
||||||
|
return self._entry.xview_scroll(number, what)
|
||||||
|
@ -114,9 +114,6 @@ class CTkFrame(CTkBaseClass):
|
|||||||
self._canvas.tag_lower("inner_parts")
|
self._canvas.tag_lower("inner_parts")
|
||||||
self._canvas.tag_lower("border_parts")
|
self._canvas.tag_lower("border_parts")
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "fg_color" in kwargs:
|
if "fg_color" in kwargs:
|
||||||
self._fg_color = kwargs.pop("fg_color")
|
self._fg_color = kwargs.pop("fg_color")
|
||||||
|
@ -115,9 +115,6 @@ class CTkLabel(CTkBaseClass):
|
|||||||
|
|
||||||
self._canvas.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
self._canvas.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "anchor" in kwargs:
|
if "anchor" in kwargs:
|
||||||
self._anchor = kwargs.pop("anchor")
|
self._anchor = kwargs.pop("anchor")
|
||||||
|
@ -193,9 +193,6 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
|
|
||||||
self._canvas.update_idletasks()
|
self._canvas.update_idletasks()
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "state" in kwargs:
|
if "state" in kwargs:
|
||||||
self._state = kwargs.pop("state")
|
self._state = kwargs.pop("state")
|
||||||
|
@ -152,9 +152,6 @@ class CTkProgressBar(CTkBaseClass):
|
|||||||
fill=ThemeManager.single_color(self._progress_color, self._appearance_mode),
|
fill=ThemeManager.single_color(self._progress_color, self._appearance_mode),
|
||||||
outline=ThemeManager.single_color(self._progress_color, self._appearance_mode))
|
outline=ThemeManager.single_color(self._progress_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "fg_color" in kwargs:
|
if "fg_color" in kwargs:
|
||||||
self._fg_color = kwargs.pop("fg_color")
|
self._fg_color = kwargs.pop("fg_color")
|
||||||
|
@ -158,9 +158,6 @@ class CTkRadioButton(CTkBaseClass):
|
|||||||
|
|
||||||
self._text_label.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
self._text_label.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "text" in kwargs:
|
if "text" in kwargs:
|
||||||
self._text = kwargs.pop("text")
|
self._text = kwargs.pop("text")
|
||||||
|
@ -150,9 +150,6 @@ class CTkScrollbar(CTkBaseClass):
|
|||||||
|
|
||||||
self._canvas.update_idletasks()
|
self._canvas.update_idletasks()
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "fg_color" in kwargs:
|
if "fg_color" in kwargs:
|
||||||
self._fg_color = kwargs.pop("fg_color")
|
self._fg_color = kwargs.pop("fg_color")
|
||||||
|
@ -190,9 +190,6 @@ class CTkSlider(CTkBaseClass):
|
|||||||
fill=ThemeManager.single_color(self._button_color, self._appearance_mode),
|
fill=ThemeManager.single_color(self._button_color, self._appearance_mode),
|
||||||
outline=ThemeManager.single_color(self._button_color, self._appearance_mode))
|
outline=ThemeManager.single_color(self._button_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "state" in kwargs:
|
if "state" in kwargs:
|
||||||
self._state = kwargs.pop("state")
|
self._state = kwargs.pop("state")
|
||||||
|
@ -207,9 +207,6 @@ class CTkSwitch(CTkBaseClass):
|
|||||||
|
|
||||||
self._text_label.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
self._text_label.configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "text" in kwargs:
|
if "text" in kwargs:
|
||||||
self._text = kwargs.pop("text")
|
self._text = kwargs.pop("text")
|
||||||
|
@ -118,9 +118,6 @@ class CTkTextbox(CTkBaseClass):
|
|||||||
self._canvas.tag_lower("inner_parts")
|
self._canvas.tag_lower("inner_parts")
|
||||||
self._canvas.tag_lower("border_parts")
|
self._canvas.tag_lower("border_parts")
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
return self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
if "fg_color" in kwargs:
|
if "fg_color" in kwargs:
|
||||||
self._fg_color = kwargs.pop("fg_color")
|
self._fg_color = kwargs.pop("fg_color")
|
||||||
|
@ -105,9 +105,6 @@ 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, **kwargs):
|
|
||||||
return self.configure(**kwargs)
|
|
||||||
|
|
||||||
def configure(self, **kwargs):
|
def configure(self, **kwargs):
|
||||||
if "fg_color" in kwargs:
|
if "fg_color" in kwargs:
|
||||||
self._fg_color = kwargs.pop("fg_color")
|
self._fg_color = kwargs.pop("fg_color")
|
||||||
|
@ -15,7 +15,7 @@ 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
|
from .widget_helper_functions import pop_from_dict_by_set
|
||||||
|
|
||||||
|
|
||||||
class CTkBaseClass(tkinter.Frame):
|
class CTkBaseClass(tkinter.Frame):
|
||||||
@ -23,7 +23,7 @@ class CTkBaseClass(tkinter.Frame):
|
|||||||
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 """
|
||||||
|
|
||||||
# attributes that are passed to and managed by the tkinter frame only:
|
# attributes that are passed to and managed by the tkinter frame only:
|
||||||
_valid_tk_frame_attributes = {"cursor"}
|
_valid_tk_frame_attributes = {"cursor", "master"}
|
||||||
|
|
||||||
def __init__(self, *args,
|
def __init__(self, *args,
|
||||||
width: int,
|
width: int,
|
||||||
@ -32,7 +32,10 @@ class CTkBaseClass(tkinter.Frame):
|
|||||||
bg_color: Union[str, tuple] = None,
|
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, **pop_from_dict_by_set(kwargs, self._valid_tk_frame_attributes))
|
||||||
|
|
||||||
|
# check if kwargs is empty, if not raise error for unsupported arguments
|
||||||
|
self._check_kwargs_empty(kwargs, raise_error=True)
|
||||||
|
|
||||||
# dimensions
|
# dimensions
|
||||||
self._current_width = width # _current_width and _current_height in pixel, represent current size of the widget
|
self._current_width = width # _current_width and _current_height in pixel, represent current size of the widget
|
||||||
@ -85,6 +88,18 @@ class CTkBaseClass(tkinter.Frame):
|
|||||||
self.master.config = new_configure
|
self.master.config = new_configure
|
||||||
self.master.configure = new_configure
|
self.master.configure = new_configure
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_kwargs_empty(kwargs_dict, raise_error=False) -> bool:
|
||||||
|
""" returns True if kwargs are empty, False otherwise, raises error if not empty """
|
||||||
|
|
||||||
|
if len(kwargs_dict) > 0:
|
||||||
|
if raise_error:
|
||||||
|
raise ValueError(f"{list(kwargs_dict.keys())} are not supported arguments. Look at the documentation for supported arguments.")
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
AppearanceModeTracker.remove(self._set_appearance_mode)
|
AppearanceModeTracker.remove(self._set_appearance_mode)
|
||||||
super().destroy()
|
super().destroy()
|
||||||
@ -127,10 +142,10 @@ class CTkBaseClass(tkinter.Frame):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
def config(self, *args, **kwargs):
|
||||||
return self.configure(*args, **kwargs)
|
raise AttributeError("'config' is not implemented for CTk widgets. For consistency, always use 'configure' instead.")
|
||||||
|
|
||||||
def configure(self, require_redraw=False, **kwargs):
|
def configure(self, require_redraw=False, **kwargs):
|
||||||
""" basic configure with _bg_color support, to be overridden """
|
""" basic configure with bg_color support, calls configure of tkinter.Frame, calls draw() in the end """
|
||||||
|
|
||||||
if "bg_color" in kwargs:
|
if "bg_color" in kwargs:
|
||||||
new_bg_color = kwargs.pop("bg_color")
|
new_bg_color = kwargs.pop("bg_color")
|
||||||
@ -140,21 +155,28 @@ class CTkBaseClass(tkinter.Frame):
|
|||||||
self._bg_color = new_bg_color
|
self._bg_color = new_bg_color
|
||||||
require_redraw = True
|
require_redraw = True
|
||||||
|
|
||||||
super().configure(**filter_dict_by_set(kwargs, self._valid_tk_frame_attributes))
|
super().configure(**pop_from_dict_by_set(kwargs, self._valid_tk_frame_attributes)) # configure tkinter.Frame
|
||||||
|
|
||||||
|
# if there are still items in the kwargs dict, raise ValueError
|
||||||
|
self._check_kwargs_empty(kwargs, raise_error=True)
|
||||||
|
|
||||||
if require_redraw:
|
if require_redraw:
|
||||||
self._draw()
|
self._draw()
|
||||||
|
|
||||||
def cget(self, key: str):
|
def cget(self, attribute_name: str):
|
||||||
if key == "bg_color":
|
""" basic cget with bg_color, width, height support, calls cget of tkinter.Frame """
|
||||||
|
|
||||||
|
if attribute_name == "bg_color":
|
||||||
return self._bg_color
|
return self._bg_color
|
||||||
elif key == "width":
|
elif attribute_name == "width":
|
||||||
return self._desired_width
|
return self._desired_width
|
||||||
elif key == "height":
|
elif attribute_name == "height":
|
||||||
return self._desired_height
|
return self._desired_height
|
||||||
|
|
||||||
elif key in self._valid_tk_frame_attributes:
|
elif attribute_name in self._valid_tk_frame_attributes:
|
||||||
return super().cget(key)
|
return super().cget(attribute_name) # cget of tkinter.Frame
|
||||||
|
else:
|
||||||
|
raise ValueError(f"'{attribute_name}' is not a supported argument. Look at the documentation for supported arguments.")
|
||||||
|
|
||||||
def _update_dimensions_event(self, event):
|
def _update_dimensions_event(self, event):
|
||||||
# only redraw if dimensions changed (for performance), independent of scaling
|
# only redraw if dimensions changed (for performance), independent of scaling
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
def filter_dict_by_set(dictionary: dict, valid_keys: set):
|
def filter_dict_by_set(dictionary: dict, valid_keys: set):
|
||||||
""" remove all key value pairs, where key is not in valid_keys set """
|
""" create new dict with key value pairs of dictionary, where key is in valid_keys """
|
||||||
new_dictionary = {}
|
new_dictionary = {}
|
||||||
|
|
||||||
for key, value in dictionary.items():
|
for key, value in dictionary.items():
|
||||||
@ -9,3 +9,14 @@ def filter_dict_by_set(dictionary: dict, valid_keys: set):
|
|||||||
new_dictionary[key] = value
|
new_dictionary[key] = value
|
||||||
|
|
||||||
return new_dictionary
|
return new_dictionary
|
||||||
|
|
||||||
|
|
||||||
|
def pop_from_dict_by_set(dictionary: dict, valid_keys: set):
|
||||||
|
""" remove and create new dict with key value pairs of dictionary, where key is in valid_keys """
|
||||||
|
new_dictionary = {}
|
||||||
|
|
||||||
|
for key in list(dictionary.keys()):
|
||||||
|
if key in valid_keys:
|
||||||
|
new_dictionary[key] = dictionary.pop(key)
|
||||||
|
|
||||||
|
return new_dictionary
|
||||||
|
@ -17,7 +17,7 @@ class CTkInputDialog:
|
|||||||
For detailed information check out the documentation.
|
For detailed information check out the documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self, *args,
|
||||||
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",
|
||||||
@ -27,7 +27,13 @@ class CTkInputDialog:
|
|||||||
text: 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
|
|
||||||
|
if len(args) > 0 and master is None:
|
||||||
|
self.master = args[0]
|
||||||
|
elif master is not None:
|
||||||
|
self.master = master
|
||||||
|
else:
|
||||||
|
raise ValueError("master argument is missing")
|
||||||
|
|
||||||
self._window_bg_color = ThemeManager.theme["color"]["window_bg_color"]
|
self._window_bg_color = ThemeManager.theme["color"]["window_bg_color"]
|
||||||
self._fg_color = ThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color
|
self._fg_color = ThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color
|
||||||
@ -39,14 +45,15 @@ class CTkInputDialog:
|
|||||||
self._height: int = len(text.split("\n")) * 20 + 150
|
self._height: int = len(text.split("\n")) * 20 + 150
|
||||||
self._text = text
|
self._text = text
|
||||||
|
|
||||||
self._toplevel_window = CTkToplevel()
|
self._toplevel_window = CTkToplevel(self.master)
|
||||||
self._toplevel_window.geometry(f"{280}x{self._height}")
|
self._toplevel_window.geometry(f"{280}x{self._height}")
|
||||||
self._toplevel_window.minsize(280, self._height)
|
self._toplevel_window.minsize(280, self._height)
|
||||||
self._toplevel_window.maxsize(280, self._height)
|
self._toplevel_window.maxsize(280, self._height)
|
||||||
self._toplevel_window.title(title)
|
self._toplevel_window.title(title)
|
||||||
self._toplevel_window.lift()
|
|
||||||
self._toplevel_window.focus_force()
|
self._toplevel_window.focus_force()
|
||||||
self._toplevel_window.grab_set()
|
self._toplevel_window.grab_set() # make other windows not clickable
|
||||||
|
self._toplevel_window.lift() # lift window on top
|
||||||
|
self._toplevel_window.attributes("-topmost", True) # stay on top
|
||||||
self._toplevel_window.protocol("WM_DELETE_WINDOW", self._on_closing)
|
self._toplevel_window.protocol("WM_DELETE_WINDOW", self._on_closing)
|
||||||
self._toplevel_window.after(10, self._create_widgets) # create widgets with slight delay, to avoid white flickering of background
|
self._toplevel_window.after(10, self._create_widgets) # create widgets with slight delay, to avoid white flickering of background
|
||||||
|
|
||||||
@ -99,25 +106,17 @@ class CTkInputDialog:
|
|||||||
|
|
||||||
def _ok_event(self, event=None):
|
def _ok_event(self, event=None):
|
||||||
self._user_input = self._entry.get()
|
self._user_input = self._entry.get()
|
||||||
self._running = False
|
self._toplevel_window.grab_release()
|
||||||
|
self._toplevel_window.destroy()
|
||||||
|
|
||||||
def _on_closing(self):
|
def _on_closing(self):
|
||||||
self._running = False
|
self._toplevel_window.grab_release()
|
||||||
|
self._toplevel_window.destroy()
|
||||||
|
|
||||||
def _cancel_event(self):
|
def _cancel_event(self):
|
||||||
self._running = False
|
self._toplevel_window.grab_release()
|
||||||
|
self._toplevel_window.destroy()
|
||||||
|
|
||||||
def get_input(self):
|
def get_input(self):
|
||||||
self._running = True
|
self.master.wait_window(self._toplevel_window)
|
||||||
|
|
||||||
while self._running:
|
|
||||||
try:
|
|
||||||
self._toplevel_window.update()
|
|
||||||
except Exception:
|
|
||||||
return self._user_input
|
|
||||||
finally:
|
|
||||||
time.sleep(0.01)
|
|
||||||
|
|
||||||
time.sleep(0.05)
|
|
||||||
self._toplevel_window.destroy()
|
|
||||||
return self._user_input
|
return self._user_input
|
||||||
|
@ -142,9 +142,9 @@ class CTk(tkinter.Tk):
|
|||||||
|
|
||||||
super().mainloop(*args, **kwargs)
|
super().mainloop(*args, **kwargs)
|
||||||
|
|
||||||
def resizable(self, *args, **kwargs):
|
def resizable(self, width: bool = None, height: bool = None):
|
||||||
super().resizable(*args, **kwargs)
|
super().resizable(width, height)
|
||||||
self._last_resizable_args = (args, kwargs)
|
self._last_resizable_args = ([], {"width": width, "height": height})
|
||||||
|
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
if self._appearance_mode == 1:
|
if self._appearance_mode == 1:
|
||||||
@ -225,9 +225,6 @@ class CTk(tkinter.Tk):
|
|||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, *args, **kwargs):
|
def configure(self, *args, **kwargs):
|
||||||
bg_changed = False
|
bg_changed = False
|
||||||
|
|
||||||
|
@ -161,9 +161,9 @@ class CTkToplevel(tkinter.Toplevel):
|
|||||||
self._iconify_called_after_windows_set_titlebar_color = True
|
self._iconify_called_after_windows_set_titlebar_color = True
|
||||||
super().iconify()
|
super().iconify()
|
||||||
|
|
||||||
def resizable(self, *args, **kwargs):
|
def resizable(self, width: bool = None, height: bool = None):
|
||||||
super().resizable(*args, **kwargs)
|
super().resizable(width, height)
|
||||||
self._last_resizable_args = (args, kwargs)
|
self._last_resizable_args = ([], {"width": width, "height": height})
|
||||||
|
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
if self._appearance_mode == 1:
|
if self._appearance_mode == 1:
|
||||||
@ -189,9 +189,6 @@ class CTkToplevel(tkinter.Toplevel):
|
|||||||
self._current_height = height
|
self._current_height = height
|
||||||
super().maxsize(self._apply_window_scaling(self._max_width), self._apply_window_scaling(self._max_height))
|
super().maxsize(self._apply_window_scaling(self._max_width), self._apply_window_scaling(self._max_height))
|
||||||
|
|
||||||
def config(self, *args, **kwargs):
|
|
||||||
self.configure(*args, **kwargs)
|
|
||||||
|
|
||||||
def configure(self, *args, **kwargs):
|
def configure(self, *args, **kwargs):
|
||||||
bg_changed = False
|
bg_changed = False
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ class App(customtkinter.CTk):
|
|||||||
|
|
||||||
self.title("CustomTkinter complex_example.py")
|
self.title("CustomTkinter complex_example.py")
|
||||||
self.geometry(f"{920}x{500}")
|
self.geometry(f"{920}x{500}")
|
||||||
|
self.minsize(700, 400)
|
||||||
|
self.maxsize(1200, 700)
|
||||||
self.protocol("WM_DELETE_WINDOW", self.on_closing) # call .on_closing() when app gets closed
|
self.protocol("WM_DELETE_WINDOW", self.on_closing) # call .on_closing() when app gets closed
|
||||||
|
|
||||||
# configure grid layout (4x4)
|
# configure grid layout (4x4)
|
||||||
@ -126,7 +128,7 @@ class App(customtkinter.CTk):
|
|||||||
self.progressbar_1.start()
|
self.progressbar_1.start()
|
||||||
|
|
||||||
def open_input_dialog(self):
|
def open_input_dialog(self):
|
||||||
dialog = customtkinter.CTkInputDialog(master=None, text="Type in a number:", title="CTkInputDialog")
|
dialog = customtkinter.CTkInputDialog(master=self, text="Type in a number:", title="CTkInputDialog")
|
||||||
print("CTkInputDialog:", dialog.get_input())
|
print("CTkInputDialog:", dialog.get_input())
|
||||||
|
|
||||||
def change_appearance_mode(self, new_appearance_mode: str):
|
def change_appearance_mode(self, new_appearance_mode: str):
|
||||||
@ -139,10 +141,8 @@ class App(customtkinter.CTk):
|
|||||||
|
|
||||||
def sidebar_button_callback(self):
|
def sidebar_button_callback(self):
|
||||||
print("sidebar_button click")
|
print("sidebar_button click")
|
||||||
|
|
||||||
self.entry.delete(0, tkinter.END)
|
self.entry.delete(0, tkinter.END)
|
||||||
|
|
||||||
|
|
||||||
def on_closing(self, event=0):
|
def on_closing(self, event=0):
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
|
@ -76,14 +76,14 @@ class TestCTk():
|
|||||||
def test_configure(self):
|
def test_configure(self):
|
||||||
print(" -> test_configure: ", end="")
|
print(" -> test_configure: ", end="")
|
||||||
self.root_ctk.configure(bg="white")
|
self.root_ctk.configure(bg="white")
|
||||||
assert self.root_ctk.fg_color == "white"
|
assert self.root_ctk.cget("fg_color") == "white"
|
||||||
|
|
||||||
self.root_ctk.configure(background="red")
|
self.root_ctk.configure(background="red")
|
||||||
assert self.root_ctk.fg_color == "red"
|
assert self.root_ctk.cget("fg_color") == "red"
|
||||||
assert self.root_ctk.cget("bg") == "red"
|
assert self.root_ctk.cget("bg") == "red"
|
||||||
|
|
||||||
self.root_ctk.config(fg_color=("green", "#FFFFFF"))
|
self.root_ctk.config(fg_color=("green", "#FFFFFF"))
|
||||||
assert self.root_ctk.fg_color == ("green", "#FFFFFF")
|
assert self.root_ctk.cget("fg_color") == ("green", "#FFFFFF")
|
||||||
print("successful")
|
print("successful")
|
||||||
|
|
||||||
def test_appearance_mode(self):
|
def test_appearance_mode(self):
|
||||||
|
55
test/unit_tests/test_ctk_entry.py
Normal file
55
test/unit_tests/test_ctk_entry.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import customtkinter
|
||||||
|
import time
|
||||||
|
|
||||||
|
app = customtkinter.CTk()
|
||||||
|
|
||||||
|
entry_1 = customtkinter.CTkEntry(app, width=100, height=25)
|
||||||
|
entry_1.pack(padx=20, pady=20)
|
||||||
|
entry_2 = customtkinter.CTkEntry(app, width=100, height=25)
|
||||||
|
entry_2.pack(padx=20, pady=20)
|
||||||
|
|
||||||
|
txt_var = customtkinter.StringVar(value="test")
|
||||||
|
|
||||||
|
entry_1.configure(width=300,
|
||||||
|
height=35,
|
||||||
|
corner_radius=1000,
|
||||||
|
border_width=4,
|
||||||
|
bg_color="green",
|
||||||
|
fg_color=("red", "yellow"),
|
||||||
|
border_color="blue",
|
||||||
|
text_color=("brown", "green"),
|
||||||
|
placeholder_text_color="blue",
|
||||||
|
textvariable=txt_var,
|
||||||
|
placeholder_text="new_placholder",
|
||||||
|
font=("Times New Roman", -8, "bold"),
|
||||||
|
state="normal",
|
||||||
|
insertborderwidth=5,
|
||||||
|
insertwidth=10,
|
||||||
|
justify="right",
|
||||||
|
show="+")
|
||||||
|
|
||||||
|
assert entry_1.cget("width") == 300
|
||||||
|
assert entry_1.cget("height") == 35
|
||||||
|
assert entry_1.cget("corner_radius") == 1000
|
||||||
|
assert entry_1.cget("border_width") == 4
|
||||||
|
assert entry_1.cget("bg_color") == "green"
|
||||||
|
assert entry_1.cget("fg_color") == ("red", "yellow")
|
||||||
|
assert entry_1.cget("border_color") == "blue"
|
||||||
|
assert entry_1.cget("text_color") == ("brown", "green")
|
||||||
|
assert entry_1.cget("placeholder_text_color") == "blue"
|
||||||
|
assert entry_1.cget("textvariable") == txt_var
|
||||||
|
assert entry_1.cget("placeholder_text") == "new_placholder"
|
||||||
|
assert entry_1.cget("font") == ("Times New Roman", -8, "bold")
|
||||||
|
assert entry_1.cget("state") == "normal"
|
||||||
|
assert entry_1.cget("insertborderwidth") == 5
|
||||||
|
assert entry_1.cget("insertwidth") == 10
|
||||||
|
assert entry_1.cget("justify") == "right"
|
||||||
|
# assert entry_1.cget("show") == "+" # somehow does not work, maybe a tkinter bug?
|
||||||
|
|
||||||
|
def test_textvariable():
|
||||||
|
txt_var.set("test_2")
|
||||||
|
print(entry_1.get())
|
||||||
|
assert entry_1.get() == "test_2"
|
||||||
|
|
||||||
|
app.after(500, test_textvariable)
|
||||||
|
app.mainloop()
|
Loading…
Reference in New Issue
Block a user