From 4616561c1303d034c9613c30e95291cf507181ac Mon Sep 17 00:00:00 2001 From: Tom Schimansky Date: Wed, 5 Oct 2022 21:11:46 +0200 Subject: [PATCH] added focus wrapper functions to all widgets --- customtkinter/widgets/ctk_button.py | 15 ++++++++++++--- customtkinter/widgets/ctk_checkbox.py | 9 +++++++++ customtkinter/widgets/ctk_combobox.py | 9 +++++++++ customtkinter/widgets/ctk_entry.py | 3 +++ customtkinter/widgets/ctk_frame.py | 3 +++ customtkinter/widgets/ctk_label.py | 9 +++++++++ customtkinter/widgets/ctk_optionmenu.py | 9 +++++++++ customtkinter/widgets/ctk_progressbar.py | 9 +++++++++ customtkinter/widgets/ctk_radiobutton.py | 9 +++++++++ customtkinter/widgets/ctk_scrollbar.py | 9 +++++++++ customtkinter/widgets/ctk_slider.py | 9 +++++++++ customtkinter/widgets/ctk_switch.py | 9 +++++++++ customtkinter/widgets/ctk_tabview.py | 8 ++++++++ customtkinter/widgets/ctk_textbox.py | 12 ++++++++++++ test/manual_integration_tests/test_textbox.py | 10 +++++++++- 15 files changed, 128 insertions(+), 4 deletions(-) diff --git a/customtkinter/widgets/ctk_button.py b/customtkinter/widgets/ctk_button.py index ec6ec1c..a4bdff4 100644 --- a/customtkinter/widgets/ctk_button.py +++ b/customtkinter/widgets/ctk_button.py @@ -54,9 +54,9 @@ class CTkButton(CTkBaseClass): # text, font, image self._image = image - self._image_label = None + self._image_label: Union[tkinter.Label, None] = None self._text = text - self._text_label = None + self._text_label: Union[tkinter.Label, None] = None self._font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if font == "default_theme" else font # callback and hover functionality @@ -65,7 +65,7 @@ class CTkButton(CTkBaseClass): self._state = state self._hover = hover self._compound = compound - self._click_animation_running = False + self._click_animation_running: bool = False # configure grid system (2x2) self.grid_rowconfigure(0, weight=1) @@ -420,3 +420,12 @@ class CTkButton(CTkBaseClass): canvas_bind_return, label_bind_return = funcid.split(" + ") self._canvas.unbind(sequence, canvas_bind_return) self._text_label.unbind(sequence, label_bind_return) + + def focus(self): + return self._text_label.focus() + + def focus_set(self): + return self._text_label.focus_set() + + def focus_force(self): + return self._text_label.focus_force() diff --git a/customtkinter/widgets/ctk_checkbox.py b/customtkinter/widgets/ctk_checkbox.py index 8c1aaf8..7cad678 100644 --- a/customtkinter/widgets/ctk_checkbox.py +++ b/customtkinter/widgets/ctk_checkbox.py @@ -371,3 +371,12 @@ class CTkCheckBox(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Canvas """ return self._canvas.unbind(sequence, funcid) + + def focus(self): + return self._text_label.focus() + + def focus_set(self): + return self._text_label.focus_set() + + def focus_force(self): + return self._text_label.focus_force() diff --git a/customtkinter/widgets/ctk_combobox.py b/customtkinter/widgets/ctk_combobox.py index aa7286d..f17fe1f 100644 --- a/customtkinter/widgets/ctk_combobox.py +++ b/customtkinter/widgets/ctk_combobox.py @@ -357,3 +357,12 @@ class CTkComboBox(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Entry """ return self._entry.unbind(sequence, funcid) + + def focus(self): + return self._entry.focus() + + def focus_set(self): + return self._entry.focus_set() + + def focus_force(self): + return self._entry.focus_force() diff --git a/customtkinter/widgets/ctk_entry.py b/customtkinter/widgets/ctk_entry.py index d404a43..ef5ad99 100644 --- a/customtkinter/widgets/ctk_entry.py +++ b/customtkinter/widgets/ctk_entry.py @@ -313,6 +313,9 @@ class CTkEntry(CTkBaseClass): def focus(self): return self._entry.focus() + def focus_set(self): + return self._entry.focus_set() + def focus_force(self): return self._entry.focus_force() diff --git a/customtkinter/widgets/ctk_frame.py b/customtkinter/widgets/ctk_frame.py index adda306..e27c604 100644 --- a/customtkinter/widgets/ctk_frame.py +++ b/customtkinter/widgets/ctk_frame.py @@ -90,6 +90,9 @@ class CTkFrame(CTkBaseClass): def _draw(self, no_color_updates=False): + if not self._canvas.winfo_exists(): + return + requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._current_width), self._apply_widget_scaling(self._current_height), self._apply_widget_scaling(self._corner_radius), diff --git a/customtkinter/widgets/ctk_label.py b/customtkinter/widgets/ctk_label.py index 5c79084..102cb46 100644 --- a/customtkinter/widgets/ctk_label.py +++ b/customtkinter/widgets/ctk_label.py @@ -193,3 +193,12 @@ class CTkLabel(CTkBaseClass): canvas_bind_return, label_bind_return = funcid.split(" + ") self._canvas.unbind(sequence, canvas_bind_return) self._text_label.unbind(sequence, label_bind_return) + + def focus(self): + return self._text_label.focus() + + def focus_set(self): + return self._text_label.focus_set() + + def focus_force(self): + return self._text_label.focus_force() diff --git a/customtkinter/widgets/ctk_optionmenu.py b/customtkinter/widgets/ctk_optionmenu.py index bafafe6..8317480 100644 --- a/customtkinter/widgets/ctk_optionmenu.py +++ b/customtkinter/widgets/ctk_optionmenu.py @@ -369,3 +369,12 @@ class CTkOptionMenu(CTkBaseClass): canvas_bind_return, label_bind_return = funcid.split(" + ") self._canvas.unbind(sequence, canvas_bind_return) self._text_label.unbind(sequence, label_bind_return) + + def focus(self): + return self._text_label.focus() + + def focus_set(self): + return self._text_label.focus_set() + + def focus_force(self): + return self._text_label.focus_force() diff --git a/customtkinter/widgets/ctk_progressbar.py b/customtkinter/widgets/ctk_progressbar.py index 8c32c8c..5b34ffc 100644 --- a/customtkinter/widgets/ctk_progressbar.py +++ b/customtkinter/widgets/ctk_progressbar.py @@ -290,3 +290,12 @@ class CTkProgressBar(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Canvas """ return self._canvas.unbind(sequence, funcid) + + def focus(self): + return self._canvas.focus() + + def focus_set(self): + return self._canvas.focus_set() + + def focus_force(self): + return self._canvas.focus_force() diff --git a/customtkinter/widgets/ctk_radiobutton.py b/customtkinter/widgets/ctk_radiobutton.py index b80c428..42f07fb 100644 --- a/customtkinter/widgets/ctk_radiobutton.py +++ b/customtkinter/widgets/ctk_radiobutton.py @@ -333,3 +333,12 @@ class CTkRadioButton(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Canvas """ return self._canvas.unbind(sequence, funcid) + + def focus(self): + return self._text_label.focus() + + def focus_set(self): + return self._text_label.focus_set() + + def focus_force(self): + return self._text_label.focus_force() diff --git a/customtkinter/widgets/ctk_scrollbar.py b/customtkinter/widgets/ctk_scrollbar.py index 6924a7b..86731ce 100644 --- a/customtkinter/widgets/ctk_scrollbar.py +++ b/customtkinter/widgets/ctk_scrollbar.py @@ -257,3 +257,12 @@ class CTkScrollbar(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Canvas """ return self._canvas.unbind(sequence, funcid) + + def focus(self): + return self._canvas.focus() + + def focus_set(self): + return self._canvas.focus_set() + + def focus_force(self): + return self._canvas.focus_force() diff --git a/customtkinter/widgets/ctk_slider.py b/customtkinter/widgets/ctk_slider.py index 06600c5..cce9379 100644 --- a/customtkinter/widgets/ctk_slider.py +++ b/customtkinter/widgets/ctk_slider.py @@ -373,3 +373,12 @@ class CTkSlider(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Canvas """ return self._canvas.unbind(sequence, funcid) + + def focus(self): + return self._canvas.focus() + + def focus_set(self): + return self._canvas.focus_set() + + def focus_force(self): + return self._canvas.focus_force() diff --git a/customtkinter/widgets/ctk_switch.py b/customtkinter/widgets/ctk_switch.py index 05f6ab1..62269cf 100644 --- a/customtkinter/widgets/ctk_switch.py +++ b/customtkinter/widgets/ctk_switch.py @@ -382,3 +382,12 @@ class CTkSwitch(CTkBaseClass): def unbind(self, sequence, funcid=None): """ called on the tkinter.Canvas """ return self._canvas.unbind(sequence, funcid) + + def focus(self): + return self._text_label.focus() + + def focus_set(self): + return self._text_label.focus_set() + + def focus_force(self): + return self._text_label.focus_force() diff --git a/customtkinter/widgets/ctk_tabview.py b/customtkinter/widgets/ctk_tabview.py index e69de29..1f9f5b3 100644 --- a/customtkinter/widgets/ctk_tabview.py +++ b/customtkinter/widgets/ctk_tabview.py @@ -0,0 +1,8 @@ +from .widget_base_class import CTkBaseClass + + +class CTkTabview(CTkBaseClass): + def __init__(self, *args, + **kwargs): + super().__init__(*args, **kwargs) + pass diff --git a/customtkinter/widgets/ctk_textbox.py b/customtkinter/widgets/ctk_textbox.py index 5d6ad00..a86a149 100644 --- a/customtkinter/widgets/ctk_textbox.py +++ b/customtkinter/widgets/ctk_textbox.py @@ -203,6 +203,9 @@ class CTkTextbox(CTkBaseClass): def _draw(self, no_color_updates=False): + if not self._canvas.winfo_exists(): + return + requires_recoloring = self._draw_engine.draw_rounded_rect_with_border(self._apply_widget_scaling(self._current_width), self._apply_widget_scaling(self._current_height), self._apply_widget_scaling(self._corner_radius), @@ -313,6 +316,15 @@ class CTkTextbox(CTkBaseClass): """ called on the tkinter.Text """ return self._textbox.unbind(sequence, funcid) + def focus(self): + return self._textbox.focus() + + def focus_set(self): + return self._textbox.focus_set() + + def focus_force(self): + return self._textbox.focus_force() + def insert(self, index, text, tags=None): self._check_if_scrollbars_needed() return self._textbox.insert(index, text, tags) diff --git a/test/manual_integration_tests/test_textbox.py b/test/manual_integration_tests/test_textbox.py index fddef5d..c8d2e0c 100644 --- a/test/manual_integration_tests/test_textbox.py +++ b/test/manual_integration_tests/test_textbox.py @@ -10,7 +10,7 @@ app = customtkinter.CTk() app.title("test_scrollbar.py") app.geometry("800x1200") app.grid_rowconfigure(0, weight=1) -app.grid_columnconfigure((0, 1, 2, 3), weight=1) +app.grid_columnconfigure((0, 1, 2, 3, 4), weight=1) textbox_1 = customtkinter.CTkTextbox(app, fg_color=None, corner_radius=0, border_spacing=0) textbox_1.grid(row=0, column=0, sticky="nsew") @@ -34,6 +34,7 @@ textbox_2.grid(row=2, column=0, sticky="nsew", padx=20, pady=20) textbox_2.insert("0.0", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.\n\n" * 20) textbox_2 = customtkinter.CTkTextbox(frame_1, wrap="none", corner_radius=60, border_width=15) + #fg_color="blue", scrollbar_color="yellow", text_color="red") textbox_2.grid(row=3, column=0, sticky="nsew", padx=20, pady=20) textbox_2.insert("0.0", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.\n\n" * 20) @@ -91,5 +92,12 @@ textbox_3 = customtkinter.CTkTextbox(frame_3, corner_radius=0, border_width=0, a textbox_3.grid(row=4, column=0, sticky="nsew", padx=20, pady=20) textbox_3.insert("0.0", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.\n\n" * 20) +textbox_4 = customtkinter.CTkTextbox(app, fg_color=None, corner_radius=0) +textbox_4.grid(row=0, column=4, sticky="nsew") +textbox_4.insert("0.0", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.\n\n" * 20) +scrollbar4 = customtkinter.CTkScrollbar(app, command=textbox_4.yview) +scrollbar4.grid(row=0, column=5, sticky="nsew") +textbox_4.configure(yscrollcommand=scrollbar4.set) + app.after(3000, lambda: customtkinter.set_appearance_mode("light")) app.mainloop()