From 5977dcbaeb3690ba945cc693c0c79430935f3b5b Mon Sep 17 00:00:00 2001 From: Tom Schimansky Date: Fri, 14 Oct 2022 18:51:44 +0200 Subject: [PATCH] added _set_dimensions method to every widget, now called from CTkBaseClass, added separate width and height attributes for small canvas in CTkCheckbox, CTkRadioButton, CTkSwitch --- customtkinter/widgets/ctk_button.py | 1 - customtkinter/widgets/ctk_checkbox.py | 105 +++++++++++++-------- customtkinter/widgets/ctk_combobox.py | 1 - customtkinter/widgets/ctk_entry.py | 1 - customtkinter/widgets/ctk_frame.py | 2 - customtkinter/widgets/ctk_label.py | 1 - customtkinter/widgets/ctk_optionmenu.py | 2 - customtkinter/widgets/ctk_progressbar.py | 3 - customtkinter/widgets/ctk_radiobutton.py | 87 +++++++++++------ customtkinter/widgets/ctk_scrollbar.py | 1 - customtkinter/widgets/ctk_slider.py | 3 - customtkinter/widgets/ctk_switch.py | 66 +++++++++---- customtkinter/widgets/ctk_tabview.py | 3 +- customtkinter/widgets/ctk_textbox.py | 8 -- customtkinter/widgets/widget_base_class.py | 1 + 15 files changed, 177 insertions(+), 108 deletions(-) diff --git a/customtkinter/widgets/ctk_button.py b/customtkinter/widgets/ctk_button.py index 7b505f8..099f18e 100644 --- a/customtkinter/widgets/ctk_button.py +++ b/customtkinter/widgets/ctk_button.py @@ -97,7 +97,6 @@ class CTkButton(CTkBaseClass): self._canvas.bind("", self._on_leave) self._canvas.bind("", self._clicked) self._canvas.bind("", self._clicked) - super().bind('', self._update_dimensions_event) # configure cursor and initial draw self._set_cursor() diff --git a/customtkinter/widgets/ctk_checkbox.py b/customtkinter/widgets/ctk_checkbox.py index ab09386..fcfa56e 100644 --- a/customtkinter/widgets/ctk_checkbox.py +++ b/customtkinter/widgets/ctk_checkbox.py @@ -17,8 +17,10 @@ class CTkCheckBox(CTkBaseClass): def __init__(self, master: any = None, - width: int = 24, + width: int = 100, height: int = 24, + checkbox_width: int = 24, + checkbox_height: int = 24, corner_radius: Union[int, str] = "default_theme", border_width: Union[int, str] = "default_theme", @@ -44,6 +46,10 @@ class CTkCheckBox(CTkBaseClass): # transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass super().__init__(master=master, bg_color=bg_color, width=width, height=height, **kwargs) + # dimensions + self._checkbox_width = checkbox_width + self._checkbox_height = checkbox_height + # color self._fg_color = ThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color self._hover_color = ThemeManager.theme["color"]["button_hover"] if hover_color == "default_theme" else hover_color @@ -84,13 +90,13 @@ class CTkCheckBox(CTkBaseClass): highlightthickness=0, width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) - self._bg_canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=3, rowspan=1, sticky="nswe") + self._bg_canvas.grid(row=0, column=0, columnspan=3, sticky="nswe") self._canvas = CTkCanvas(master=self, highlightthickness=0, - width=self._apply_widget_scaling(self._desired_width), - height=self._apply_widget_scaling(self._desired_height)) - self._canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1, rowspan=1) + width=self._apply_widget_scaling(self._checkbox_width), + height=self._apply_widget_scaling(self._checkbox_height)) + self._canvas.grid(row=0, column=0, sticky="e") self._draw_engine = DrawEngine(self._canvas) self._canvas.bind("", self._on_enter) @@ -99,11 +105,13 @@ class CTkCheckBox(CTkBaseClass): self._text_label = tkinter.Label(master=self, bd=0, + padx=0, + pady=0, text=self._text, justify=tkinter.LEFT, font=self._apply_font_scaling(self._font), textvariable=self._textvariable) - self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") + self._text_label.grid(row=0, column=2, sticky="w") self._text_label["anchor"] = "w" self._text_label.bind("", self._on_enter) @@ -125,10 +133,18 @@ class CTkCheckBox(CTkBaseClass): self._text_label.configure(font=self._apply_font_scaling(self._font)) self._canvas.delete("checkmark") - self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) - self._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._checkbox_width), + height=self._apply_widget_scaling(self._checkbox_height)) self._draw() + def _set_dimensions(self, width: int = None, height: int = None): + super()._set_dimensions(width, height) + + self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), + height=self._apply_widget_scaling(self._desired_height)) + def destroy(self): if self._variable is not None: self._variable.trace_remove("write", self._variable_callback_name) @@ -136,49 +152,60 @@ class CTkCheckBox(CTkBaseClass): super().destroy() def _draw(self, no_color_updates=False): - requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._current_width), - self._apply_widget_scaling(self._current_height), + requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._checkbox_width), + self._apply_widget_scaling(self._checkbox_height), self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(self._border_width)) if self._check_state is True: - self._draw_engine.draw_checkmark(self._apply_widget_scaling(self._current_width), - self._apply_widget_scaling(self._current_height), - self._apply_widget_scaling(self._current_height * 0.58)) + self._draw_engine.draw_checkmark(self._apply_widget_scaling(self._checkbox_width), + self._apply_widget_scaling(self._checkbox_height), + self._apply_widget_scaling(self._checkbox_height * 0.58)) else: self._canvas.delete("checkmark") - self._bg_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)) + if no_color_updates is False or requires_recoloring: + self._bg_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)) - if self._check_state is True: - self._canvas.itemconfig("inner_parts", - outline=ThemeManager.single_color(self._fg_color, self._appearance_mode), - fill=ThemeManager.single_color(self._fg_color, self._appearance_mode)) - self._canvas.itemconfig("border_parts", - outline=ThemeManager.single_color(self._fg_color, self._appearance_mode), - fill=ThemeManager.single_color(self._fg_color, self._appearance_mode)) + if self._check_state is True: + self._canvas.itemconfig("inner_parts", + outline=ThemeManager.single_color(self._fg_color, self._appearance_mode), + fill=ThemeManager.single_color(self._fg_color, self._appearance_mode)) + self._canvas.itemconfig("border_parts", + outline=ThemeManager.single_color(self._fg_color, self._appearance_mode), + fill=ThemeManager.single_color(self._fg_color, self._appearance_mode)) - if "create_line" in self._canvas.gettags("checkmark"): - self._canvas.itemconfig("checkmark", fill=ThemeManager.single_color(self._checkmark_color, self._appearance_mode)) + if "create_line" in self._canvas.gettags("checkmark"): + self._canvas.itemconfig("checkmark", fill=ThemeManager.single_color(self._checkmark_color, self._appearance_mode)) + else: + self._canvas.itemconfig("checkmark", fill=ThemeManager.single_color(self._checkmark_color, self._appearance_mode)) else: - self._canvas.itemconfig("checkmark", fill=ThemeManager.single_color(self._checkmark_color, self._appearance_mode)) - else: - self._canvas.itemconfig("inner_parts", - outline=ThemeManager.single_color(self._bg_color, self._appearance_mode), - fill=ThemeManager.single_color(self._bg_color, self._appearance_mode)) - self._canvas.itemconfig("border_parts", - outline=ThemeManager.single_color(self._border_color, self._appearance_mode), - fill=ThemeManager.single_color(self._border_color, self._appearance_mode)) + self._canvas.itemconfig("inner_parts", + outline=ThemeManager.single_color(self._bg_color, self._appearance_mode), + fill=ThemeManager.single_color(self._bg_color, self._appearance_mode)) + self._canvas.itemconfig("border_parts", + outline=ThemeManager.single_color(self._border_color, self._appearance_mode), + fill=ThemeManager.single_color(self._border_color, self._appearance_mode)) - if self._state == tkinter.DISABLED: - self._text_label.configure(fg=(ThemeManager.single_color(self._text_color_disabled, self._appearance_mode))) - else: - self._text_label.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) + if self._state == tkinter.DISABLED: + self._text_label.configure(fg=(ThemeManager.single_color(self._text_color_disabled, self._appearance_mode))) + else: + self._text_label.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) - 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 configure(self, require_redraw=False, **kwargs): + if "checkbox_width" in kwargs: + self._checkbox_width = kwargs.pop("checkbox_width") + self._canvas.configure(width=self._apply_widget_scaling(self._checkbox_width)) + require_redraw = True + + if "checkbox_height" in kwargs: + self._checkbox_height = kwargs.pop("checkbox_height") + self._canvas.configure(height=self._apply_widget_scaling(self._checkbox_height)) + require_redraw = True + if "text" in kwargs: self._text = kwargs.pop("text") self._text_label.configure(text=self._text) @@ -234,6 +261,10 @@ class CTkCheckBox(CTkBaseClass): return self._corner_radius elif attribute_name == "border_width": return self._border_width + elif attribute_name == "checkbox_width": + return self._checkbox_width + elif attribute_name == "checkbox_height": + return self._checkbox_height elif attribute_name == "fg_color": return self._fg_color diff --git a/customtkinter/widgets/ctk_combobox.py b/customtkinter/widgets/ctk_combobox.py index 72ea7e7..d09fc39 100644 --- a/customtkinter/widgets/ctk_combobox.py +++ b/customtkinter/widgets/ctk_combobox.py @@ -119,7 +119,6 @@ class CTkComboBox(CTkBaseClass): self._canvas.tag_bind("dropdown_arrow", "", self._on_leave) self._canvas.tag_bind("right_parts", "", self._clicked) self._canvas.tag_bind("dropdown_arrow", "", self._clicked) - super().bind('', self._update_dimensions_event) if self._variable is not None: self._entry.configure(textvariable=self._variable) diff --git a/customtkinter/widgets/ctk_entry.py b/customtkinter/widgets/ctk_entry.py index f8a1518..282bf66 100644 --- a/customtkinter/widgets/ctk_entry.py +++ b/customtkinter/widgets/ctk_entry.py @@ -97,7 +97,6 @@ class CTkEntry(CTkBaseClass): self._check_kwargs_empty(kwargs, raise_error=True) - super().bind('', self._update_dimensions_event) self._entry.bind('', self._entry_focus_out) self._entry.bind('', self._entry_focus_in) diff --git a/customtkinter/widgets/ctk_frame.py b/customtkinter/widgets/ctk_frame.py index 10d8dbb..b8b54c3 100644 --- a/customtkinter/widgets/ctk_frame.py +++ b/customtkinter/widgets/ctk_frame.py @@ -62,8 +62,6 @@ class CTkFrame(CTkBaseClass): self._draw_engine = DrawEngine(self._canvas) self._overwrite_preferred_drawing_method = overwrite_preferred_drawing_method - super().bind('', self._update_dimensions_event) - self._draw() def winfo_children(self) -> List[any]: diff --git a/customtkinter/widgets/ctk_label.py b/customtkinter/widgets/ctk_label.py index e9ee0fc..05d6b4a 100644 --- a/customtkinter/widgets/ctk_label.py +++ b/customtkinter/widgets/ctk_label.py @@ -76,7 +76,6 @@ class CTkLabel(CTkBaseClass): self._check_kwargs_empty(kwargs, raise_error=True) - super().bind('', self._update_dimensions_event) self._draw() def _set_scaling(self, *args, **kwargs): diff --git a/customtkinter/widgets/ctk_optionmenu.py b/customtkinter/widgets/ctk_optionmenu.py index 1f61c44..89d6350 100644 --- a/customtkinter/widgets/ctk_optionmenu.py +++ b/customtkinter/widgets/ctk_optionmenu.py @@ -129,8 +129,6 @@ class CTkOptionMenu(CTkBaseClass): self._text_label.bind("", self._clicked) self._text_label.bind("", self._clicked) - super().bind('', self._update_dimensions_event) - self._draw() # initial draw if self._variable is not None: diff --git a/customtkinter/widgets/ctk_progressbar.py b/customtkinter/widgets/ctk_progressbar.py index 3d60807..6bdb783 100644 --- a/customtkinter/widgets/ctk_progressbar.py +++ b/customtkinter/widgets/ctk_progressbar.py @@ -81,9 +81,6 @@ class CTkProgressBar(CTkBaseClass): self._canvas.grid(row=0, column=0, rowspan=1, columnspan=1, sticky="nswe") self._draw_engine = DrawEngine(self._canvas) - # Each time an item is resized due to pack position mode, the binding Configure is called on the widget - super().bind('', self._update_dimensions_event) - self._draw() # initial draw if self._variable is not None: diff --git a/customtkinter/widgets/ctk_radiobutton.py b/customtkinter/widgets/ctk_radiobutton.py index 548a582..3e654e2 100644 --- a/customtkinter/widgets/ctk_radiobutton.py +++ b/customtkinter/widgets/ctk_radiobutton.py @@ -17,8 +17,10 @@ class CTkRadioButton(CTkBaseClass): def __init__(self, master: any = None, - width: int = 22, + width: int = 100, height: int = 22, + radiobutton_width: int = 22, + radiobutton_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", @@ -43,6 +45,10 @@ class CTkRadioButton(CTkBaseClass): # transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass super().__init__(master=master, bg_color=bg_color, width=width, height=height, **kwargs) + # dimensions + self._radiobutton_width = radiobutton_width + self._radiobutton_height = radiobutton_height + # color self._fg_color = ThemeManager.theme["color"]["button"] if fg_color == "default_theme" else fg_color self._hover_color = ThemeManager.theme["color"]["button_hover"] if hover_color == "default_theme" else hover_color @@ -81,13 +87,13 @@ class CTkRadioButton(CTkBaseClass): highlightthickness=0, width=self._apply_widget_scaling(self._current_width), height=self._apply_widget_scaling(self._current_height)) - self._bg_canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=3, rowspan=1, sticky="nswe") + self._bg_canvas.grid(row=0, column=0, columnspan=3, sticky="nswe") self._canvas = CTkCanvas(master=self, highlightthickness=0, - width=self._apply_widget_scaling(self._current_width), - height=self._apply_widget_scaling(self._current_height)) - self._canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1) + width=self._apply_widget_scaling(self._radiobutton_width), + height=self._apply_widget_scaling(self._radiobutton_height)) + self._canvas.grid(row=0, column=0) self._draw_engine = DrawEngine(self._canvas) self._canvas.bind("", self._on_enter) @@ -96,11 +102,13 @@ class CTkRadioButton(CTkBaseClass): self._text_label = tkinter.Label(master=self, bd=0, + padx=0, + pady=0, text=self._text, justify=tkinter.LEFT, font=self._apply_font_scaling(self._font), textvariable=self._textvariable) - self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") + self._text_label.grid(row=0, column=2, sticky="w") self._text_label["anchor"] = "w" self._text_label.bind("", self._on_enter) @@ -120,10 +128,18 @@ class CTkRadioButton(CTkBaseClass): self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6)) self._text_label.configure(font=self._apply_font_scaling(self._font)) - self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) - self._canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) + 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._radiobutton_width), + height=self._apply_widget_scaling(self._radiobutton_height)) self._draw() + def _set_dimensions(self, width: int = None, height: int = None): + super()._set_dimensions(width, height) + + self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), + height=self._apply_widget_scaling(self._desired_height)) + def destroy(self): if self._variable is not None: self._variable.trace_remove("write", self._variable_callback_name) @@ -131,35 +147,46 @@ class CTkRadioButton(CTkBaseClass): super().destroy() def _draw(self, no_color_updates=False): - requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._current_width), - self._apply_widget_scaling(self._current_height), + requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._radiobutton_width), + self._apply_widget_scaling(self._radiobutton_height), self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(self._border_width)) - self._bg_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)) + if no_color_updates is False or requires_recoloring: + self._bg_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)) - if self._check_state is False: - self._canvas.itemconfig("border_parts", - outline=ThemeManager.single_color(self._border_color, self._appearance_mode), - fill=ThemeManager.single_color(self._border_color, self._appearance_mode)) - else: - self._canvas.itemconfig("border_parts", - outline=ThemeManager.single_color(self._fg_color, self._appearance_mode), - fill=ThemeManager.single_color(self._fg_color, self._appearance_mode)) + if self._check_state is False: + self._canvas.itemconfig("border_parts", + outline=ThemeManager.single_color(self._border_color, self._appearance_mode), + fill=ThemeManager.single_color(self._border_color, self._appearance_mode)) + else: + self._canvas.itemconfig("border_parts", + outline=ThemeManager.single_color(self._fg_color, self._appearance_mode), + fill=ThemeManager.single_color(self._fg_color, self._appearance_mode)) - self._canvas.itemconfig("inner_parts", - outline=ThemeManager.single_color(self._bg_color, self._appearance_mode), - fill=ThemeManager.single_color(self._bg_color, self._appearance_mode)) + self._canvas.itemconfig("inner_parts", + outline=ThemeManager.single_color(self._bg_color, self._appearance_mode), + fill=ThemeManager.single_color(self._bg_color, self._appearance_mode)) - if self._state == tkinter.DISABLED: - self._text_label.configure(fg=ThemeManager.single_color(self._text_color_disabled, self._appearance_mode)) - else: - self._text_label.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) + if self._state == tkinter.DISABLED: + self._text_label.configure(fg=ThemeManager.single_color(self._text_color_disabled, self._appearance_mode)) + else: + self._text_label.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) - 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 configure(self, require_redraw=False, **kwargs): + if "radiobutton_width" in kwargs: + self._radiobutton_width = kwargs.pop("radiobutton_width") + self._canvas.configure(width=self._apply_widget_scaling(self._radiobutton_width)) + require_redraw = True + + if "radiobutton_height" in kwargs: + self._radiobutton_height = kwargs.pop("radiobutton_height") + self._canvas.configure(height=self._apply_widget_scaling(self._radiobutton_height)) + require_redraw = True + if "text" in kwargs: self._text = kwargs.pop("text") self._text_label.configure(text=self._text) @@ -220,6 +247,10 @@ class CTkRadioButton(CTkBaseClass): return self._border_width_unchecked elif attribute_name == "border_width_checked": return self._border_width_checked + elif attribute_name == "radiobutton_width": + return self._radiobutton_width + elif attribute_name == "radiobutton_height": + return self._radiobutton_height elif attribute_name == "fg_color": return self._fg_color diff --git a/customtkinter/widgets/ctk_scrollbar.py b/customtkinter/widgets/ctk_scrollbar.py index 3dd5c4d..554c90e 100644 --- a/customtkinter/widgets/ctk_scrollbar.py +++ b/customtkinter/widgets/ctk_scrollbar.py @@ -76,7 +76,6 @@ class CTkScrollbar(CTkBaseClass): self._canvas.tag_bind("border_parts", "", self._clicked) self._canvas.bind("", self._clicked) self._canvas.bind("", self._mouse_scroll_event) - super().bind('', self._update_dimensions_event) self._draw() diff --git a/customtkinter/widgets/ctk_slider.py b/customtkinter/widgets/ctk_slider.py index f34a599..27b8c65 100644 --- a/customtkinter/widgets/ctk_slider.py +++ b/customtkinter/widgets/ctk_slider.py @@ -100,9 +100,6 @@ class CTkSlider(CTkBaseClass): self._canvas.bind("", self._clicked) self._canvas.bind("", self._clicked) - # Each time an item is resized due to pack position mode, the binding Configure is called on the widget - super().bind('', self._update_dimensions_event) - self._set_cursor() self._draw() # initial draw diff --git a/customtkinter/widgets/ctk_switch.py b/customtkinter/widgets/ctk_switch.py index dbdfe7f..410846c 100644 --- a/customtkinter/widgets/ctk_switch.py +++ b/customtkinter/widgets/ctk_switch.py @@ -17,8 +17,10 @@ class CTkSwitch(CTkBaseClass): def __init__(self, master: any = None, - width: int = 36, - height: int = 18, + width: int = 100, + height: int = 24, + switch_width: int = 36, + switch_height: int = 18, corner_radius: Union[int, str] = "default_theme", border_width: Union[int, str] = "default_theme", button_length: Union[int, str] = "default_theme", @@ -45,6 +47,10 @@ class CTkSwitch(CTkBaseClass): # transfer basic functionality (_bg_color, size, _appearance_mode, scaling) to CTkBaseClass super().__init__(master=master, bg_color=bg_color, width=width, height=height, **kwargs) + # dimensions + self._switch_width = switch_width + self._switch_height = switch_height + # color self._border_color = border_color self._fg_color = ThemeManager.theme["color"]["switch"] if fg_color == "default_theme" else fg_color @@ -86,13 +92,13 @@ class CTkSwitch(CTkBaseClass): highlightthickness=0, width=self._apply_widget_scaling(self._current_width), height=self._apply_widget_scaling(self._current_height)) - self._bg_canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=3, rowspan=1, sticky="nswe") + self._bg_canvas.grid(row=0, column=0, columnspan=3, sticky="nswe") self._canvas = CTkCanvas(master=self, highlightthickness=0, - width=self._apply_widget_scaling(self._current_width), - height=self._apply_widget_scaling(self._current_height)) - self._canvas.grid(row=0, column=0, padx=0, pady=0, columnspan=1, sticky="nswe") + width=self._apply_widget_scaling(self._switch_width), + height=self._apply_widget_scaling(self._switch_height)) + self._canvas.grid(row=0, column=0, sticky="nswe") self._draw_engine = DrawEngine(self._canvas) self._canvas.bind("", self._on_enter) @@ -101,11 +107,13 @@ class CTkSwitch(CTkBaseClass): self._text_label = tkinter.Label(master=self, bd=0, + padx=0, + pady=0, text=self._text, justify=tkinter.LEFT, font=self._apply_font_scaling(self._font), textvariable=self._textvariable) - self._text_label.grid(row=0, column=2, padx=0, pady=0, sticky="w") + self._text_label.grid(row=0, column=2, sticky="w") self._text_label["anchor"] = "w" self._text_label.bind("", self._on_enter) @@ -125,10 +133,18 @@ class CTkSwitch(CTkBaseClass): self.grid_columnconfigure(1, weight=0, minsize=self._apply_widget_scaling(6)) self._text_label.configure(font=self._apply_font_scaling(self._font)) - self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) - self._canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height)) + 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._switch_width), + height=self._apply_widget_scaling(self._switch_height)) self._draw() + def _set_dimensions(self, width: int = None, height: int = None): + super()._set_dimensions(width, height) + + self._bg_canvas.configure(width=self._apply_widget_scaling(self._desired_width), + height=self._apply_widget_scaling(self._desired_height)) + def destroy(self): # remove variable_callback from variable callbacks if variable exists if self._variable is not None: @@ -161,16 +177,16 @@ class CTkSwitch(CTkBaseClass): def _draw(self, no_color_updates=False): if self._check_state is True: - requires_recoloring = self._draw_engine.draw_rounded_slider_with_border_and_button(self._apply_widget_scaling(self._current_width), - self._apply_widget_scaling(self._current_height), + requires_recoloring = self._draw_engine.draw_rounded_slider_with_border_and_button(self._apply_widget_scaling(self._switch_width), + self._apply_widget_scaling(self._switch_height), self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(self._border_width), self._apply_widget_scaling(self._button_length), self._apply_widget_scaling(self._corner_radius), 1, "w") else: - requires_recoloring = self._draw_engine.draw_rounded_slider_with_border_and_button(self._apply_widget_scaling(self._current_width), - self._apply_widget_scaling(self._current_height), + requires_recoloring = self._draw_engine.draw_rounded_slider_with_border_and_button(self._apply_widget_scaling(self._switch_width), + self._apply_widget_scaling(self._switch_height), self._apply_widget_scaling(self._corner_radius), self._apply_widget_scaling(self._border_width), self._apply_widget_scaling(self._button_length), @@ -201,14 +217,24 @@ class CTkSwitch(CTkBaseClass): self._canvas.itemconfig("slider_parts", fill=ThemeManager.single_color(self._button_color, self._appearance_mode), outline=ThemeManager.single_color(self._button_color, self._appearance_mode)) - if self._state == tkinter.DISABLED: - self._text_label.configure(fg=(ThemeManager.single_color(self._text_color_disabled, self._appearance_mode))) - else: - self._text_label.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) + if self._state == tkinter.DISABLED: + self._text_label.configure(fg=(ThemeManager.single_color(self._text_color_disabled, self._appearance_mode))) + else: + self._text_label.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode)) - 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 configure(self, require_redraw=False, **kwargs): + if "switch_width" in kwargs: + self._switch_width = kwargs.pop("switch_width") + self._canvas.configure(width=self._apply_widget_scaling(self._switch_width)) + require_redraw = True + + if "switch_height" in kwargs: + self._switch_height = kwargs.pop("switch_height") + self._canvas.configure(height=self._apply_widget_scaling(self._switch_height)) + require_redraw = True + if "text" in kwargs: self._text = kwargs.pop("text") self._text_label.configure(text=self._text) @@ -277,6 +303,10 @@ class CTkSwitch(CTkBaseClass): return self._border_width elif attribute_name == "button_length": return self._button_length + elif attribute_name == "switch_width": + return self._switch_width + elif attribute_name == "switch_height": + return self._switch_height elif attribute_name == "fg_color": return self._fg_color diff --git a/customtkinter/widgets/ctk_tabview.py b/customtkinter/widgets/ctk_tabview.py index 8c507bf..ee9ad23 100644 --- a/customtkinter/widgets/ctk_tabview.py +++ b/customtkinter/widgets/ctk_tabview.py @@ -92,10 +92,9 @@ class CTkTabview(CTkBaseClass): self._tab_dict: Dict[str, CTkFrame] = {} self._name_list: List[str] = [] # list of unique tab names in order of tabs self._current_name: str = "" - self._command = command - super().bind('', self._update_dimensions_event) + self._draw() def _segmented_button_callback(self, selected_name): self._current_name = selected_name diff --git a/customtkinter/widgets/ctk_textbox.py b/customtkinter/widgets/ctk_textbox.py index c20baa4..6647eef 100644 --- a/customtkinter/widgets/ctk_textbox.py +++ b/customtkinter/widgets/ctk_textbox.py @@ -104,9 +104,6 @@ class CTkTextbox(CTkBaseClass): orientation="vertical", command=self._textbox.yview) self._textbox.configure(yscrollcommand=self._y_scrollbar.set) - #self._y_scrollbar.grid(row=0, column=1, rowspan=1, columnspan=1, sticky="ns", - # padx=(self._apply_widget_scaling(3), self._apply_widget_scaling(self._border_spacing + self._border_width)), - # pady=(self._apply_widget_scaling(self._corner_radius + self._border_width), 0)) self._x_scrollbar = CTkScrollbar(self, height=8, @@ -118,15 +115,10 @@ class CTkTextbox(CTkBaseClass): orientation="horizontal", command=self._textbox.xview) self._textbox.configure(xscrollcommand=self._x_scrollbar.set) - #self._x_scrollbar.grid(row=1, column=0, rowspan=1, columnspan=1, sticky="ew", - # pady=(self._apply_widget_scaling(3), self._apply_widget_scaling(self._border_spacing + self._border_width)), - # padx=(self._apply_widget_scaling(self._corner_radius + self._border_width), 0)) self._create_grid_for_text_and_scrollbars(re_grid_textbox=True, re_grid_x_scrollbar=True, re_grid_y_scrollbar=True) self.after(50, self._check_if_scrollbars_needed) - - super().bind('', self._update_dimensions_event) self._draw() def _create_grid_for_text_and_scrollbars(self, re_grid_textbox=False, re_grid_x_scrollbar=False, re_grid_y_scrollbar=False): diff --git a/customtkinter/widgets/widget_base_class.py b/customtkinter/widgets/widget_base_class.py index 54a610c..12a0a71 100644 --- a/customtkinter/widgets/widget_base_class.py +++ b/customtkinter/widgets/widget_base_class.py @@ -67,6 +67,7 @@ class CTkBaseClass(tkinter.Frame): self._bg_color: Union[str, Tuple[str, str]] = self._detect_color_of_master() if bg_color is None else bg_color super().configure(bg=ThemeManager.single_color(self._bg_color, self._appearance_mode)) + super().bind('', self._update_dimensions_event) # overwrite configure methods of master when master is tkinter widget, so that bg changes get applied on child CTk widget as well if isinstance(self.master, (tkinter.Tk, tkinter.Toplevel, tkinter.Frame)) and not isinstance(self.master, (CTkBaseClass, CTk, CTkToplevel)):