From 40474d6905b1b6f86e95e452fe0c415bc617b099 Mon Sep 17 00:00:00 2001 From: Tom Schimansky Date: Tue, 4 Oct 2022 03:03:43 +0200 Subject: [PATCH] added unbind method for all widgets, fixed bind methods, fixed textbox configure --- customtkinter/widgets/ctk_button.py | 6 ++++- customtkinter/widgets/ctk_checkbox.py | 4 +++ customtkinter/widgets/ctk_combobox.py | 10 +++++--- customtkinter/widgets/ctk_entry.py | 4 +++ customtkinter/widgets/ctk_frame.py | 6 ++++- customtkinter/widgets/ctk_label.py | 6 ++++- customtkinter/widgets/ctk_optionmenu.py | 11 +++++--- customtkinter/widgets/ctk_progressbar.py | 7 +++++- customtkinter/widgets/ctk_radiobutton.py | 5 ++++ customtkinter/widgets/ctk_scrollbar.py | 7 +++++- customtkinter/widgets/ctk_slider.py | 7 +++++- customtkinter/widgets/ctk_switch.py | 5 ++++ customtkinter/widgets/ctk_textbox.py | 32 ++++++++++++++++-------- 13 files changed, 88 insertions(+), 22 deletions(-) diff --git a/customtkinter/widgets/ctk_button.py b/customtkinter/widgets/ctk_button.py index da9c56a..1cd70ab 100644 --- a/customtkinter/widgets/ctk_button.py +++ b/customtkinter/widgets/ctk_button.py @@ -86,7 +86,7 @@ class CTkButton(CTkBaseClass): self._canvas.bind("", self._on_leave) self._canvas.bind("", self._clicked) self._canvas.bind("", self._clicked) - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) # configure cursor and initial draw self._set_cursor() @@ -412,3 +412,7 @@ class CTkButton(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_checkbox.py b/customtkinter/widgets/ctk_checkbox.py index 7dfe654..ac85ccb 100644 --- a/customtkinter/widgets/ctk_checkbox.py +++ b/customtkinter/widgets/ctk_checkbox.py @@ -367,3 +367,7 @@ class CTkCheckBox(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_combobox.py b/customtkinter/widgets/ctk_combobox.py index 790a1f7..2721e0c 100644 --- a/customtkinter/widgets/ctk_combobox.py +++ b/customtkinter/widgets/ctk_combobox.py @@ -118,7 +118,7 @@ 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) - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) if self._variable is not None: self._entry.configure(textvariable=self._variable) @@ -351,5 +351,9 @@ class CTkComboBox(CTkBaseClass): self._open_dropdown_menu() def bind(self, sequence=None, command=None, add=None): - """ called on the tkinter.Canvas """ - return self._canvas.bind(sequence, command, add) + """ called on the tkinter.Entry """ + return self._entry.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Entry """ + return self._entry.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_entry.py b/customtkinter/widgets/ctk_entry.py index bbf1cce..f452dc8 100644 --- a/customtkinter/widgets/ctk_entry.py +++ b/customtkinter/widgets/ctk_entry.py @@ -263,6 +263,10 @@ class CTkEntry(CTkBaseClass): """ called on the tkinter.Entry """ return self._entry.bind(sequence, command, add) + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Entry """ + return self._entry.bind(sequence, funcid) + def _activate_placeholder(self): if self._entry.get() == "" and self._placeholder_text is not None and (self._textvariable is None or self._textvariable == ""): self._placeholder_text_active = True diff --git a/customtkinter/widgets/ctk_frame.py b/customtkinter/widgets/ctk_frame.py index 4fa5cf2..14b55df 100644 --- a/customtkinter/widgets/ctk_frame.py +++ b/customtkinter/widgets/ctk_frame.py @@ -58,7 +58,7 @@ class CTkFrame(CTkBaseClass): self._draw_engine = DrawEngine(self._canvas) self._overwrite_preferred_drawing_method = overwrite_preferred_drawing_method - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) self._draw() @@ -161,3 +161,7 @@ class CTkFrame(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_label.py b/customtkinter/widgets/ctk_label.py index 25b501c..e5537eb 100644 --- a/customtkinter/widgets/ctk_label.py +++ b/customtkinter/widgets/ctk_label.py @@ -76,7 +76,7 @@ class CTkLabel(CTkBaseClass): self._check_kwargs_empty(kwargs, raise_error=True) - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) self._draw() def _set_scaling(self, *args, **kwargs): @@ -185,3 +185,7 @@ class CTkLabel(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Label """ return self._text_label.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Label """ + return self._text_label.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_optionmenu.py b/customtkinter/widgets/ctk_optionmenu.py index 0dabe7f..3e9d81c 100644 --- a/customtkinter/widgets/ctk_optionmenu.py +++ b/customtkinter/widgets/ctk_optionmenu.py @@ -125,7 +125,7 @@ class CTkOptionMenu(CTkBaseClass): self._text_label.bind("", self._clicked) self._text_label.bind("", self._clicked) - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) self._draw() # initial draw @@ -303,6 +303,7 @@ class CTkOptionMenu(CTkBaseClass): return self._command elif attribute_name == "dynamic_resizing": return self._dynamic_resizing + else: return super().cget(attribute_name) @@ -358,5 +359,9 @@ class CTkOptionMenu(CTkBaseClass): self._open_dropdown_menu() def bind(self, sequence=None, command=None, add=None): - """ called on the tkinter.Canvas """ - return self._canvas.bind(sequence, command, add) + """ called on the tkinter.Label """ + return self._text_label.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Label """ + return self._text_label.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_progressbar.py b/customtkinter/widgets/ctk_progressbar.py index 9d19679..0e31f33 100644 --- a/customtkinter/widgets/ctk_progressbar.py +++ b/customtkinter/widgets/ctk_progressbar.py @@ -81,7 +81,7 @@ class CTkProgressBar(CTkBaseClass): 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 - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) self._draw() # initial draw @@ -222,6 +222,7 @@ class CTkProgressBar(CTkBaseClass): return self._determinate_speed elif attribute_name == "indeterminate_speed": return self._indeterminate_speed + else: return super().cget(attribute_name) @@ -285,3 +286,7 @@ class CTkProgressBar(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_radiobutton.py b/customtkinter/widgets/ctk_radiobutton.py index e547ab8..89fdddc 100644 --- a/customtkinter/widgets/ctk_radiobutton.py +++ b/customtkinter/widgets/ctk_radiobutton.py @@ -247,6 +247,7 @@ class CTkRadioButton(CTkBaseClass): return self._hover elif attribute_name == "command": return self._command + else: return super().cget(attribute_name) @@ -328,3 +329,7 @@ class CTkRadioButton(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_scrollbar.py b/customtkinter/widgets/ctk_scrollbar.py index 201a527..4c550ea 100644 --- a/customtkinter/widgets/ctk_scrollbar.py +++ b/customtkinter/widgets/ctk_scrollbar.py @@ -75,7 +75,7 @@ class CTkScrollbar(CTkBaseClass): self._canvas.tag_bind("border_parts", "", self._clicked) self._canvas.bind("", self._clicked) self._canvas.bind("", self._mouse_scroll_event) - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) self._draw() @@ -203,6 +203,7 @@ class CTkScrollbar(CTkBaseClass): return self._command elif attribute_name == "orientation": return self._orientation + else: return super().cget(attribute_name) @@ -252,3 +253,7 @@ class CTkScrollbar(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_slider.py b/customtkinter/widgets/ctk_slider.py index ade50d4..7b8af7c 100644 --- a/customtkinter/widgets/ctk_slider.py +++ b/customtkinter/widgets/ctk_slider.py @@ -100,7 +100,7 @@ class CTkSlider(CTkBaseClass): self._canvas.bind("", self._clicked) # Each time an item is resized due to pack position mode, the binding Configure is called on the widget - self.bind('', self._update_dimensions_event) + super().bind('', self._update_dimensions_event) self._set_cursor() self._draw() # initial draw @@ -287,6 +287,7 @@ class CTkSlider(CTkBaseClass): return self._variable elif attribute_name == "orientation": return self._orientation + else: return super().cget(attribute_name) @@ -368,3 +369,7 @@ class CTkSlider(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_switch.py b/customtkinter/widgets/ctk_switch.py index 3b7c37a..90bf2c1 100644 --- a/customtkinter/widgets/ctk_switch.py +++ b/customtkinter/widgets/ctk_switch.py @@ -308,6 +308,7 @@ class CTkSwitch(CTkBaseClass): return self._command elif attribute_name == "state": return self._state + else: return super().cget(attribute_name) @@ -377,3 +378,7 @@ class CTkSwitch(CTkBaseClass): def bind(self, sequence=None, command=None, add=None): """ called on the tkinter.Canvas """ return self._canvas.bind(sequence, command, add) + + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Canvas """ + return self._canvas.bind(sequence, funcid) diff --git a/customtkinter/widgets/ctk_textbox.py b/customtkinter/widgets/ctk_textbox.py index 4aad34f..523533f 100644 --- a/customtkinter/widgets/ctk_textbox.py +++ b/customtkinter/widgets/ctk_textbox.py @@ -6,6 +6,8 @@ from ..theme_manager import ThemeManager from ..draw_engine import DrawEngine from .widget_base_class import CTkBaseClass +from .widget_helper_functions import pop_from_dict_by_set + class CTkTextbox(CTkBaseClass): """ @@ -13,6 +15,13 @@ class CTkTextbox(CTkBaseClass): For detailed information check out the documentation. """ + # attributes that are passed to and managed by the tkinter textbox only: + _valid_tk_text_attributes = {"autoseparators", "cursor", "exportselection", + "insertborderwidth", "insertofftime", "insertontime", "insertwidth", + "maxundo", "padx", "pady", "selectborderwidth", "spacing1", + "spacing2", "spacing3", "state", "tabs", "takefocus", "undo", "wrap", + "xscrollcommand", "yscrollcommand"} + def __init__(self, *args, width: int = 200, height: int = 200, @@ -66,12 +75,14 @@ class CTkTextbox(CTkBaseClass): font=self._font, highlightthickness=0, relief="flat", - insertbackground=ThemeManager.single_color(("black", "white"), self._appearance_mode), + insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode), bg=ThemeManager.single_color(self._fg_color, self._appearance_mode), - **kwargs) + **pop_from_dict_by_set(kwargs, self._valid_tk_text_attributes)) self._textbox.grid(row=0, column=0, padx=self._corner_radius, pady=self._corner_radius, rowspan=1, columnspan=1, sticky="nsew") - self.bind('', self._update_dimensions_event) + self._check_kwargs_empty(kwargs, raise_error=True) + + super().bind('', self._update_dimensions_event) self._draw() def _set_scaling(self, *args, **kwargs): @@ -113,7 +124,7 @@ class CTkTextbox(CTkBaseClass): self._textbox.configure(fg=ThemeManager.single_color(self._text_color, self._appearance_mode), bg=ThemeManager.single_color(self._fg_color, self._appearance_mode), - insertbackground=ThemeManager.single_color(("black", "white"), self._appearance_mode)) + insertbackground=ThemeManager.single_color(self._text_color, self._appearance_mode)) self._canvas.tag_lower("inner_parts") self._canvas.tag_lower("border_parts") @@ -153,12 +164,8 @@ class CTkTextbox(CTkBaseClass): if "font" in kwargs: raise ValueError("No attribute named font. Use text_font instead of font for CTk widgets") - if "bg_color" in kwargs: - super().configure(bg_color=kwargs.pop("bg_color"), require_redraw=require_redraw) - else: - super().configure(require_redraw=require_redraw) - - self._textbox.configure(**kwargs) + self._textbox.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_text_attributes)) + super().configure(require_redraw=require_redraw, **kwargs) def cget(self, attribute_name: str) -> any: if attribute_name == "corner_radius": @@ -175,6 +182,7 @@ class CTkTextbox(CTkBaseClass): elif attribute_name == "font": return self._font + else: return super().cget(attribute_name) @@ -182,6 +190,10 @@ class CTkTextbox(CTkBaseClass): """ called on the tkinter.Text """ return self._textbox.bind(sequence, command, add) + def unbind(self, sequence, funcid=None): + """ called on the tkinter.Text """ + return self._textbox.bind(sequence, funcid) + def yview(self, *args): return self._textbox.yview(*args)