1 Commits

Author SHA1 Message Date
344b30e684 fixed scrollable frame mouse wheel on linux #1356 2023-07-11 14:15:06 +02:00
22 changed files with 99 additions and 168 deletions

View File

@ -17,12 +17,6 @@
---
<div align="center">
<h3>
Official website: https://customtkinter.tomschimansky.com
</h3>
</div>
CustomTkinter is a python UI-library based on Tkinter, which provides new, modern and
fully customizable widgets. They are created and used like normal Tkinter widgets and
can also be used in combination with normal Tkinter elements. The widgets
@ -49,13 +43,14 @@ pip3 install customtkinter
## Documentation
The **official** documentation can be found here:
The **official** documentation can be found in the Wiki Tab here:
**➡️ https://customtkinter.tomschimansky.com/documentation**.
**--> [Documentation](https://github.com/TomSchimansky/CustomTkinter/wiki)**.
## Example Program
To test customtkinter you can try this simple example with only a single button:
```python
import tkinter
import customtkinter
customtkinter.set_appearance_mode("System") # Modes: system (default), light, dark
@ -69,7 +64,7 @@ def button_function():
# Use CTkButton instead of tkinter Button
button = customtkinter.CTkButton(master=app, text="CTkButton", command=button_function)
button.place(relx=0.5, rely=0.5, anchor=customtkinter.CENTER)
button.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)
app.mainloop()
```

View File

@ -1,4 +1,4 @@
__version__ = "5.2.0"
__version__ = "5.1.1"
import os
import sys

View File

@ -34,7 +34,7 @@
"text_color":["gray10", "#DCE4EE"],
"placeholder_text_color": ["gray52", "gray62"]
},
"CTkCheckBox": {
"CTkCheckbox": {
"corner_radius": 6,
"border_width": 3,
"fg_color": ["#3B8ED0", "#1F6AA5"],
@ -48,14 +48,14 @@
"corner_radius": 1000,
"border_width": 3,
"button_length": 0,
"fg_color": ["#939BA2", "#4A4D50"],
"fg_Color": ["#939BA2", "#4A4D50"],
"progress_color": ["#3B8ED0", "#1F6AA5"],
"button_color": ["gray36", "#D5D9DE"],
"button_hover_color": ["gray20", "gray100"],
"text_color": ["gray10", "#DCE4EE"],
"text_color_disabled": ["gray60", "gray45"]
},
"CTkRadioButton": {
"CTkRadiobutton": {
"corner_radius": 1000,
"border_width_checked": 6,
"border_width_unchecked": 3,

View File

@ -34,7 +34,7 @@
"text_color": ["gray14", "gray84"],
"placeholder_text_color": ["gray52", "gray62"]
},
"CTkCheckBox": {
"CTkCheckbox": {
"corner_radius": 6,
"border_width": 3,
"fg_color": ["#3a7ebf", "#1f538d"],
@ -48,14 +48,14 @@
"corner_radius": 1000,
"border_width": 3,
"button_length": 0,
"fg_color": ["#939BA2", "#4A4D50"],
"fg_Color": ["#939BA2", "#4A4D50"],
"progress_color": ["#3a7ebf", "#1f538d"],
"button_color": ["gray36", "#D5D9DE"],
"button_hover_color": ["gray20", "gray100"],
"text_color": ["gray14", "gray84"],
"text_color_disabled": ["gray60", "gray45"]
},
"CTkRadioButton": {
"CTkRadiobutton": {
"corner_radius": 1000,
"border_width_checked": 6,
"border_width_unchecked": 3,
@ -127,9 +127,6 @@
"scrollbar_button_color": ["gray55", "gray41"],
"scrollbar_button_hover_color": ["gray40", "gray53"]
},
"CTkScrollableFrame": {
"label_fg_color": ["gray80", "gray21"]
},
"DropdownMenu": {
"fg_color": ["gray90", "gray20"],
"hover_color": ["gray75", "gray28"],

View File

@ -34,7 +34,7 @@
"text_color":["gray10", "#DCE4EE"],
"placeholder_text_color": ["gray52", "gray62"]
},
"CTkCheckBox": {
"CTkCheckbox": {
"corner_radius": 6,
"border_width": 3,
"fg_color": ["#2CC985", "#2FA572"],
@ -48,14 +48,14 @@
"corner_radius": 1000,
"border_width": 3,
"button_length": 0,
"fg_color": ["#939BA2", "#4A4D50"],
"fg_Color": ["#939BA2", "#4A4D50"],
"progress_color": ["#2CC985", "#2FA572"],
"button_color": ["gray36", "#D5D9DE"],
"button_hover_color": ["gray20", "gray100"],
"text_color": ["gray10", "#DCE4EE"],
"text_color_disabled": ["gray60", "gray45"]
},
"CTkRadioButton": {
"CTkRadiobutton": {
"corner_radius": 1000,
"border_width_checked": 6,
"border_width_unchecked": 3,
@ -127,9 +127,6 @@
"scrollbar_button_color": ["gray55", "gray41"],
"scrollbar_button_hover_color": ["gray40", "gray53"]
},
"CTkScrollableFrame": {
"label_fg_color": ["gray78", "gray23"]
},
"DropdownMenu": {
"fg_color": ["gray90", "gray20"],
"hover_color": ["gray75", "gray28"],

View File

@ -86,7 +86,7 @@ class CTkInputDialog(CTkToplevel):
hover_color=self._button_hover_color,
text_color=self._button_text_color,
text='Cancel',
command=self._cancel_event)
command=self._ok_event)
self._cancel_button.grid(row=2, column=1, columnspan=1, padx=(10, 20), pady=(0, 20), sticky="ew")
self.after(150, lambda: self._entry.focus()) # set focus to entry with slight delay, otherwise it won't work

View File

@ -19,7 +19,7 @@ class CTkToplevel(tkinter.Toplevel, CTkAppearanceModeBaseClass, CTkScalingBaseCl
For detailed information check out the documentation.
"""
_valid_tk_toplevel_arguments: set = {"master", "bd", "borderwidth", "class", "container", "cursor", "height",
_valid_tk_toplevel_arguments: set = {"bd", "borderwidth", "class", "container", "cursor", "height",
"highlightbackground", "highlightthickness", "menu", "relief",
"screen", "takefocus", "use", "visual", "width"}

View File

@ -436,7 +436,6 @@ class CTkButton(CTkBaseClass):
if "anchor" in kwargs:
self._anchor = kwargs.pop("anchor")
self._create_grid()
require_redraw = True
super().configure(require_redraw=require_redraw, **kwargs)

View File

@ -51,20 +51,20 @@ class CTkCheckBox(CTkBaseClass):
self._checkbox_height = checkbox_height
# color
self._fg_color = ThemeManager.theme["CTkCheckBox"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
self._hover_color = ThemeManager.theme["CTkCheckBox"]["hover_color"] if hover_color is None else self._check_color_type(hover_color)
self._border_color = ThemeManager.theme["CTkCheckBox"]["border_color"] if border_color is None else self._check_color_type(border_color)
self._checkmark_color = ThemeManager.theme["CTkCheckBox"]["checkmark_color"] if checkmark_color is None else self._check_color_type(checkmark_color)
self._fg_color = ThemeManager.theme["CTkCheckbox"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
self._hover_color = ThemeManager.theme["CTkCheckbox"]["hover_color"] if hover_color is None else self._check_color_type(hover_color)
self._border_color = ThemeManager.theme["CTkCheckbox"]["border_color"] if border_color is None else self._check_color_type(border_color)
self._checkmark_color = ThemeManager.theme["CTkCheckbox"]["checkmark_color"] if checkmark_color is None else self._check_color_type(checkmark_color)
# shape
self._corner_radius = ThemeManager.theme["CTkCheckBox"]["corner_radius"] if corner_radius is None else corner_radius
self._border_width = ThemeManager.theme["CTkCheckBox"]["border_width"] if border_width is None else border_width
self._corner_radius = ThemeManager.theme["CTkCheckbox"]["corner_radius"] if corner_radius is None else corner_radius
self._border_width = ThemeManager.theme["CTkCheckbox"]["border_width"] if border_width is None else border_width
# text
self._text = text
self._text_label: Union[tkinter.Label, None] = None
self._text_color = ThemeManager.theme["CTkCheckBox"]["text_color"] if text_color is None else self._check_color_type(text_color)
self._text_color_disabled = ThemeManager.theme["CTkCheckBox"]["text_color_disabled"] if text_color_disabled is None else self._check_color_type(text_color_disabled)
self._text_color = ThemeManager.theme["CTkCheckbox"]["text_color"] if text_color is None else self._check_color_type(text_color)
self._text_color_disabled = ThemeManager.theme["CTkCheckbox"]["text_color_disabled"] if text_color_disabled is None else self._check_color_type(text_color_disabled)
# font
self._font = CTkFont() if font is None else self._check_font_type(font)
@ -265,20 +265,12 @@ class CTkCheckBox(CTkBaseClass):
self._hover_color = self._check_color_type(kwargs.pop("hover_color"))
require_redraw = True
if "border_color" in kwargs:
self._border_color = self._check_color_type(kwargs.pop("border_color"))
require_redraw = True
if "checkmark_color" in kwargs:
self._checkmark_color = self._check_color_type(kwargs.pop("checkmark_color"))
require_redraw = True
if "text_color" in kwargs:
self._text_color = self._check_color_type(kwargs.pop("text_color"))
require_redraw = True
if "text_color_disabled" in kwargs:
self._text_color_disabled = self._check_color_type(kwargs.pop("text_color_disabled"))
if "border_color" in kwargs:
self._border_color = self._check_color_type(kwargs.pop("border_color"))
require_redraw = True
if "hover" in kwargs:

View File

@ -14,8 +14,6 @@ class CTkLabel(CTkBaseClass):
"""
Label with rounded corners. Default is fg_color=None (transparent fg_color).
For detailed information check out the documentation.
state argument will probably be removed because it has no effect
"""
# attributes that are passed to and managed by the tkinter entry only:
@ -31,7 +29,6 @@ class CTkLabel(CTkBaseClass):
bg_color: Union[str, Tuple[str, str]] = "transparent",
fg_color: Optional[Union[str, Tuple[str, str]]] = None,
text_color: Optional[Union[str, Tuple[str, str]]] = None,
text_color_disabled: Optional[Union[str, Tuple[str, str]]] = None,
text: str = "CTkLabel",
font: Optional[Union[tuple, CTkFont]] = None,
@ -48,14 +45,6 @@ class CTkLabel(CTkBaseClass):
self._fg_color = ThemeManager.theme["CTkLabel"]["fg_color"] if fg_color is None else self._check_color_type(fg_color, transparency=True)
self._text_color = ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else self._check_color_type(text_color)
if text_color_disabled is None:
if "text_color_disabled" in ThemeManager.theme["CTkLabel"]:
self._text_color_disabled = ThemeManager.theme["CTkLabel"]["text_color"]
else:
self._text_color_disabled = self._text_color
else:
self._text_color_disabled = self._check_color_type(text_color_disabled)
# shape
self._corner_radius = ThemeManager.theme["CTkLabel"]["corner_radius"] if corner_radius is None else corner_radius
@ -170,7 +159,6 @@ class CTkLabel(CTkBaseClass):
outline=self._apply_appearance_mode(self._bg_color))
self._label.configure(fg=self._apply_appearance_mode(self._text_color),
disabledforeground=self._apply_appearance_mode(self._text_color_disabled),
bg=self._apply_appearance_mode(self._bg_color))
else:
self._canvas.itemconfig("inner_parts",
@ -178,7 +166,6 @@ class CTkLabel(CTkBaseClass):
outline=self._apply_appearance_mode(self._fg_color))
self._label.configure(fg=self._apply_appearance_mode(self._text_color),
disabledforeground=self._apply_appearance_mode(self._text_color_disabled),
bg=self._apply_appearance_mode(self._fg_color))
self._canvas.configure(bg=self._apply_appearance_mode(self._bg_color))
@ -197,10 +184,6 @@ class CTkLabel(CTkBaseClass):
self._text_color = self._check_color_type(kwargs.pop("text_color"))
require_redraw = True
if "text_color_disabled" in kwargs:
self._text_color_disabled = self._check_color_type(kwargs.pop("text_color_disabled"))
require_redraw = True
if "text" in kwargs:
self._text = kwargs.pop("text")
self._label.configure(text=self._text)
@ -245,8 +228,6 @@ class CTkLabel(CTkBaseClass):
return self._fg_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

View File

@ -243,10 +243,6 @@ class CTkOptionMenu(CTkBaseClass):
self._text_color = self._check_color_type(kwargs.pop("text_color"))
require_redraw = True
if "text_color_disabled" in kwargs:
self._text_color_disabled = self._check_color_type(kwargs.pop("text_color_disabled"))
require_redraw = True
if "dropdown_fg_color" in kwargs:
self._dropdown_menu.configure(fg_color=kwargs.pop("dropdown_fg_color"))
@ -265,12 +261,8 @@ class CTkOptionMenu(CTkBaseClass):
self._update_font()
if "dropdown_font" in kwargs:
self._dropdown_menu.configure(font=kwargs.pop("dropdown_font"))
if "values" in kwargs:
self._values = kwargs.pop("values")
self._dropdown_menu.configure(values=self._values)
if "command" in kwargs:
self._command = kwargs.pop("command")
if "variable" in kwargs:
if self._variable is not None: # remove old callback
@ -285,15 +277,19 @@ class CTkOptionMenu(CTkBaseClass):
else:
self._variable = None
if "state" in kwargs:
self._state = kwargs.pop("state")
require_redraw = True
if "values" in kwargs:
self._values = kwargs.pop("values")
self._dropdown_menu.configure(values=self._values)
if "dropdown_font" in kwargs:
self._dropdown_menu.configure(font=kwargs.pop("dropdown_font"))
if "hover" in kwargs:
self._hover = kwargs.pop("hover")
if "command" in kwargs:
self._command = kwargs.pop("command")
if "state" in kwargs:
self._state = kwargs.pop("state")
require_redraw = True
if "dynamic_resizing" in kwargs:
self._dynamic_resizing = kwargs.pop("dynamic_resizing")

View File

@ -50,20 +50,20 @@ class CTkRadioButton(CTkBaseClass):
self._radiobutton_height = radiobutton_height
# color
self._fg_color = ThemeManager.theme["CTkRadioButton"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
self._hover_color = ThemeManager.theme["CTkRadioButton"]["hover_color"] if hover_color is None else self._check_color_type(hover_color)
self._border_color = ThemeManager.theme["CTkRadioButton"]["border_color"] if border_color is None else self._check_color_type(border_color)
self._fg_color = ThemeManager.theme["CTkRadiobutton"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
self._hover_color = ThemeManager.theme["CTkRadiobutton"]["hover_color"] if hover_color is None else self._check_color_type(hover_color)
self._border_color = ThemeManager.theme["CTkRadiobutton"]["border_color"] if border_color is None else self._check_color_type(border_color)
# shape
self._corner_radius = ThemeManager.theme["CTkRadioButton"]["corner_radius"] if corner_radius is None else corner_radius
self._border_width_unchecked = ThemeManager.theme["CTkRadioButton"]["border_width_unchecked"] if border_width_unchecked is None else border_width_unchecked
self._border_width_checked = ThemeManager.theme["CTkRadioButton"]["border_width_checked"] if border_width_checked is None else border_width_checked
self._corner_radius = ThemeManager.theme["CTkRadiobutton"]["corner_radius"] if corner_radius is None else corner_radius
self._border_width_unchecked = ThemeManager.theme["CTkRadiobutton"]["border_width_unchecked"] if border_width_unchecked is None else border_width_unchecked
self._border_width_checked = ThemeManager.theme["CTkRadiobutton"]["border_width_checked"] if border_width_checked is None else border_width_checked
# text
self._text = text
self._text_label: Union[tkinter.Label, None] = None
self._text_color = ThemeManager.theme["CTkRadioButton"]["text_color"] if text_color is None else self._check_color_type(text_color)
self._text_color_disabled = ThemeManager.theme["CTkRadioButton"]["text_color_disabled"] if text_color_disabled is None else self._check_color_type(text_color_disabled)
self._text_color = ThemeManager.theme["CTkRadiobutton"]["text_color"] if text_color is None else self._check_color_type(text_color)
self._text_color_disabled = ThemeManager.theme["CTkRadiobutton"]["text_color_disabled"] if text_color_disabled is None else self._check_color_type(text_color_disabled)
# font
self._font = CTkFont() if font is None else self._check_font_type(font)

View File

@ -74,7 +74,13 @@ class CTkScrollableFrame(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBa
self.bind("<Configure>", lambda e: self._parent_canvas.configure(scrollregion=self._parent_canvas.bbox("all")))
self._parent_canvas.bind("<Configure>", self._fit_frame_dimensions_to_canvas)
self.bind_all("<MouseWheel>", self._mouse_wheel_all, add="+")
if "linux" in sys.platform:
self.bind_all("<Button-4>", self._mouse_wheel_all, add="+")
self.bind_all("<Button-5>", self._mouse_wheel_all, add="+")
else:
self.bind_all("<MouseWheel>", self._mouse_wheel_all, add="+")
self.bind_all("<KeyPress-Shift_L>", self._keyboard_shift_press_all, add="+")
self.bind_all("<KeyPress-Shift_R>", self._keyboard_shift_press_all, add="+")
self.bind_all("<KeyRelease-Shift_L>", self._keyboard_shift_release_all, add="+")
@ -181,10 +187,10 @@ class CTkScrollableFrame(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBa
self._scrollbar.configure(fg_color=kwargs.pop("scrollbar_fg_color"))
if "scrollbar_button_color" in kwargs:
self._scrollbar.configure(button_color=kwargs.pop("scrollbar_button_color"))
self._scrollbar.configure(fg_color=kwargs.pop("scrollbar_button_color"))
if "scrollbar_button_hover_color" in kwargs:
self._scrollbar.configure(button_hover_color=kwargs.pop("scrollbar_button_hover_color"))
self._scrollbar.configure(fg_color=kwargs.pop("scrollbar_button_hover_color"))
if "label_text" in kwargs:
self._label_text = kwargs.pop("label_text")
@ -243,6 +249,8 @@ class CTkScrollableFrame(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBa
self._parent_canvas.configure(xscrollincrement=1, yscrollincrement=1)
elif sys.platform == "darwin":
self._parent_canvas.configure(xscrollincrement=4, yscrollincrement=8)
else:
self._parent_canvas.configure(xscrollincrement=30, yscrollincrement=30)
def _mouse_wheel_all(self, event):
if self.check_if_master_is_canvas(event.widget):
@ -263,10 +271,11 @@ class CTkScrollableFrame(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBa
else:
if self._shift_pressed:
if self._parent_canvas.xview() != (0.0, 1.0):
self._parent_canvas.xview("scroll", -event.delta, "units")
self._parent_canvas.xview_scroll(-1 if event.num == 4 else 1, "units")
else:
if self._parent_canvas.yview() != (0.0, 1.0):
self._parent_canvas.yview("scroll", -event.delta, "units")
self._parent_canvas.yview_scroll(-1 if event.num == 4 else 1, "units")
def _keyboard_shift_press_all(self, event):
self._shift_pressed = True

View File

@ -10,7 +10,6 @@ from .theme import ThemeManager
from .font import CTkFont
from .ctk_button import CTkButton
from .ctk_frame import CTkFrame
from .utility import check_kwargs_empty
class CTkSegmentedButton(CTkFrame):
@ -41,9 +40,10 @@ class CTkSegmentedButton(CTkFrame):
variable: Union[tkinter.Variable, None] = None,
dynamic_resizing: bool = True,
command: Union[Callable[[str], None], None] = None,
state: str = "normal"):
state: str = "normal",
**kwargs):
super().__init__(master=master, bg_color=bg_color, width=width, height=height)
super().__init__(master=master, bg_color=bg_color, width=width, height=height, **kwargs)
self._sb_fg_color = ThemeManager.theme["CTkSegmentedButton"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
@ -186,7 +186,7 @@ class CTkSegmentedButton(CTkFrame):
for index, value in enumerate(self._value_list):
self.grid_columnconfigure(index, weight=1, minsize=self._current_height)
self._buttons_dict[value].grid(row=0, column=index, sticky="nsew")
self._buttons_dict[value].grid(row=0, column=index, sticky="ew")
def _create_buttons_from_values(self):
assert len(self._buttons_dict) == 0
@ -197,23 +197,6 @@ class CTkSegmentedButton(CTkFrame):
self._configure_button_corners_for_index(index)
def configure(self, **kwargs):
if "width" in kwargs:
super().configure(width=kwargs.pop("width"))
if "height" in kwargs:
super().configure(height=kwargs.pop("height"))
if "corner_radius" in kwargs:
self._sb_corner_radius = kwargs.pop("corner_radius")
super().configure(corner_radius=self._sb_corner_radius)
for button in self._buttons_dict.values():
button.configure(corner_radius=self._sb_corner_radius)
if "border_width" in kwargs:
self._sb_border_width = kwargs.pop("border_width")
for button in self._buttons_dict.values():
button.configure(border_width=self._sb_border_width)
if "bg_color" in kwargs:
super().configure(bg_color=kwargs.pop("bg_color"))
@ -313,20 +296,14 @@ class CTkSegmentedButton(CTkFrame):
for button in self._buttons_dict.values():
button.configure(state=self._state)
check_kwargs_empty(kwargs, raise_error=True)
super().configure(**kwargs)
def cget(self, attribute_name: str) -> any:
if attribute_name == "width":
return super().cget(attribute_name)
elif attribute_name == "height":
return super().cget(attribute_name)
elif attribute_name == "corner_radius":
if attribute_name == "corner_radius":
return self._sb_corner_radius
elif attribute_name == "border_width":
return self._sb_border_width
elif attribute_name == "bg_color":
return super().cget(attribute_name)
elif attribute_name == "fg_color":
return self._sb_fg_color
elif attribute_name == "selected_color":
@ -354,7 +331,7 @@ class CTkSegmentedButton(CTkFrame):
return self._command
else:
raise ValueError(f"'{attribute_name}' is not a supported argument. Look at the documentation for supported arguments.")
return super().cget(attribute_name)
def set(self, value: str, from_variable_callback: bool = False, from_button_callback: bool = False):
if value == self._current_value:

View File

@ -54,7 +54,7 @@ class CTkSwitch(CTkBaseClass):
# color
self._border_color = self._check_color_type(border_color, transparency=True)
self._fg_color = ThemeManager.theme["CTkSwitch"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
self._fg_color = ThemeManager.theme["CTkSwitch"]["fg_Color"] if fg_color is None else self._check_color_type(fg_color)
self._progress_color = ThemeManager.theme["CTkSwitch"]["progress_color"] if progress_color is None else self._check_color_type(progress_color, transparency=True)
self._button_color = ThemeManager.theme["CTkSwitch"]["button_color"] if button_color is None else self._check_color_type(button_color)
self._button_hover_color = ThemeManager.theme["CTkSwitch"]["button_hover_color"] if button_hover_color is None else self._check_color_type(button_hover_color)
@ -299,10 +299,6 @@ class CTkSwitch(CTkBaseClass):
self._fg_color = self._check_color_type(kwargs.pop("fg_color"))
require_redraw = True
if "border_color" in kwargs:
self._border_color = self._check_color_type(kwargs.pop("border_color"), transparency=True)
require_redraw = True
if "progress_color" in kwargs:
self._progress_color = self._check_color_type(kwargs.pop("progress_color"), transparency=True)
require_redraw = True
@ -315,12 +311,8 @@ class CTkSwitch(CTkBaseClass):
self._button_hover_color = self._check_color_type(kwargs.pop("button_hover_color"))
require_redraw = True
if "text_color" in kwargs:
self._text_color = self._check_color_type(kwargs.pop("text_color"))
require_redraw = True
if "text_color_disabled" in kwargs:
self._text_color_disabled = self._check_color_type(kwargs.pop("text_color_disabled"))
if "border_color" in kwargs:
self._border_color = self._check_color_type(kwargs.pop("border_color"), transparency=True)
require_redraw = True
if "hover" in kwargs:

View File

@ -99,9 +99,9 @@ class CTkTabview(CTkBaseClass):
self._draw()
def _segmented_button_callback(self, selected_name):
self._set_grid_tab_by_name(selected_name)
self._tab_dict[self._current_name].grid_forget()
self._current_name = selected_name
self._grid_forget_all_tabs()
self._set_grid_tab_by_name(self._current_name)
if self._command is not None:
self._command()
@ -171,10 +171,9 @@ class CTkTabview(CTkBaseClass):
padx=self._apply_widget_scaling(max(self._corner_radius, self._border_width)),
pady=self._apply_widget_scaling(max(self._corner_radius, self._border_width)))
def _grid_forget_all_tabs(self, exclude_name=None):
for name, frame in self._tab_dict.items():
if name != exclude_name:
frame.grid_forget()
def _grid_forget_all_tabs(self):
for frame in self._tab_dict.values():
frame.grid_forget()
def _create_tab(self) -> CTkFrame:
new_tab = CTkFrame(self,
@ -361,8 +360,8 @@ class CTkTabview(CTkBaseClass):
if name in self._tab_dict:
self._current_name = name
self._segmented_button.set(name)
self._grid_forget_all_tabs()
self._set_grid_tab_by_name(name)
self.after(100, lambda: self._grid_forget_all_tabs(exclude_name=name))
else:
raise ValueError(f"CTkTabview has no tab named '{name}'")

View File

@ -52,10 +52,7 @@ class CTkFont(Font):
def remove_size_configure_callback(self, callback: Callable):
""" remove function, that gets called when font got configured """
try:
self._size_configure_callback_list.remove(callback)
except ValueError:
pass
self._size_configure_callback_list.remove(callback)
def create_scaled_tuple(self, font_scaling: float) -> Tuple[str, int, str]:
""" return scaled tuple representation of font in the form (family: str, size: int, style: str)"""

View File

@ -4,6 +4,6 @@ from .theme_manager import ThemeManager
try:
ThemeManager.load_theme("blue")
except FileNotFoundError as err:
raise FileNotFoundError(f"{err}\nThe .json theme file for CustomTkinter could not be found.\n" +
raise FileNotFoundError(f"{err}\n\nThe .json theme file for CustomTkinter could not be found.\n" +
f"If packaging with pyinstaller was used, have a look at the wiki:\n" +
f"https://github.com/TomSchimansky/CustomTkinter/wiki/Packaging#windows-pyinstaller-auto-py-to-exe")

View File

@ -1,6 +1,5 @@
import sys
import os
import pathlib
import json
from typing import List, Union
@ -16,8 +15,7 @@ class ThemeManager:
script_directory = os.path.dirname(os.path.abspath(__file__))
if theme_name_or_path in cls._built_in_themes:
customtkinter_path = pathlib.Path(script_directory).parent.parent.parent
with open(os.path.join(customtkinter_path, "assets", "themes", f"{theme_name_or_path}.json"), "r") as f:
with open(os.path.join(script_directory, "../../../assets", "themes", f"{theme_name_or_path}.json"), "r") as f:
cls.theme = json.load(f)
else:
with open(theme_name_or_path, "r") as f:
@ -37,12 +35,6 @@ class ThemeManager:
else:
cls.theme[key] = cls.theme[key]["Linux"]
# fix name inconsistencies
if "CTkCheckbox" in cls.theme.keys():
cls.theme["CTkCheckBox"] = cls.theme.pop("CTkCheckbox")
if "CTkRadiobutton" in cls.theme.keys():
cls.theme["CTkRadioButton"] = cls.theme.pop("CTkRadiobutton")
@classmethod
def save_theme(cls):
if cls._currently_loaded_theme is not None:

View File

@ -3,10 +3,11 @@ requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[tool.tbump]
# Uncomment this if your project is hosted on GitHub:
github_url = "https://github.com/TomSchimansky/CustomTkinter"
[tool.tbump.version]
current = "5.2.0"
current = "5.1.1"
# Example of a semver regexp.
# Make sure this matches current_version before
@ -32,3 +33,17 @@ src = "setup.cfg"
[[tool.tbump.file]]
src = "customtkinter/__init__.py"
search = "__version__ = \"{current_version}\""
# You can specify a list of commands to
# run after the files have been patched
# and before the git commit is made
# [[tool.tbump.before_commit]]
# name = "check changelog"
# cmd = "grep -q {new_version} Changelog.rst"
# Or run some commands after the git tag and the branch
# have been pushed:
# [[tool.tbump.after_push]]
# name = "publish"
# cmd = "./publish.sh"

View File

@ -1,23 +1,18 @@
[metadata]
name = customtkinter
version = 5.2.0
version = 5.1.1
description = Create modern looking GUIs with Python
long_description = A modern and customizable python UI-library based on Tkinter: https://customtkinter.tomschimansky.com
long_description = A modern and customizable python UI-library based on Tkinter: https://github.com/TomSchimansky/CustomTkinter
long_description_content_type = text/markdown
url = https://customtkinter.tomschimansky.com
url = https://github.com/TomSchimansky/CustomTkinter
author = Tom Schimansky
license = Creative Commons Zero v1.0 Universal
license_file = LICENSE
classifiers =
License :: MIT License
License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
Operating System :: OS Independent
Programming Language :: Python :: 3 :: Only
[project.urls]
homepage = https://customtkinter.tomschimansky.com
documentation = https://customtkinter.tomschimansky.com/documentation
repository = https://github.com/tomschimansky/customtkinter
[options]
python_requires = >=3.7
packages =

View File

@ -1,7 +1,5 @@
import customtkinter
customtkinter.set_default_color_theme("dark-blue")
app = customtkinter.CTk()
app.grid_columnconfigure(2, weight=1)
@ -28,7 +26,7 @@ frame_4.configure(label_text="CTkScrollableFrame")
frame_5 = customtkinter.CTkScrollableFrame(app, orientation="vertical", label_text="CTkScrollableFrame", corner_radius=0)
frame_5.grid(row=0, column=2, rowspan=2, sticky="nsew")
for i in range(100):
for i in range(20):
customtkinter.CTkCheckBox(frame_1).grid(row=i, padx=10, pady=10)
customtkinter.CTkCheckBox(frame_2).grid(row=i, padx=10, pady=10)
customtkinter.CTkCheckBox(frame_3).grid(row=0, column=i, padx=10, pady=10)