diff --git a/customtkinter/widgets/ctk_slider.py b/customtkinter/widgets/ctk_slider.py index 6fc6a5c..4712885 100644 --- a/customtkinter/widgets/ctk_slider.py +++ b/customtkinter/widgets/ctk_slider.py @@ -30,6 +30,7 @@ class CTkSlider(CTkBaseClass): command=None, variable=None, orient="horizontal", + state="normal", **kwargs): # set default dimensions according to orientation @@ -75,6 +76,7 @@ class CTkSlider(CTkBaseClass): self.variable: tkinter.Variable = variable self.variable_callback_blocked = False self.variable_callback_name = None + self.state = state self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) @@ -124,12 +126,18 @@ class CTkSlider(CTkBaseClass): super().destroy() def set_cursor(self): - if Settings.cursor_manipulation_enabled: + if self.state == "normal" and Settings.cursor_manipulation_enabled: if sys.platform == "darwin": self.configure(cursor="pointinghand") elif sys.platform.startswith("win"): self.configure(cursor="hand2") + elif self.state == "disabled" and Settings.cursor_manipulation_enabled: + if sys.platform == "darwin": + self.configure(cursor="arrow") + elif sys.platform.startswith("win"): + self.configure(cursor="arrow") + def draw(self, no_color_updates=False): if self.orient.lower() == "horizontal": orientation = "w" @@ -166,41 +174,51 @@ class CTkSlider(CTkBaseClass): self.canvas.itemconfig("progress_parts", fill=ThemeManager.single_color(self.progress_color, self._appearance_mode), outline=ThemeManager.single_color(self.progress_color, self._appearance_mode)) - 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.hover_state is True: + self.canvas.itemconfig("slider_parts", + fill=ThemeManager.single_color(self.button_hover_color, self._appearance_mode), + outline=ThemeManager.single_color(self.button_hover_color, self._appearance_mode)) + else: + 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)) def clicked(self, event=None): - if self.orient.lower() == "horizontal": - self.value = (event.x / self._current_width) / self._widget_scaling - else: - self.value = 1 - (event.y / self._current_height) / self._widget_scaling + if self.state == "normal": + if self.orient.lower() == "horizontal": + self.value = (event.x / self._current_width) / self._widget_scaling + else: + self.value = 1 - (event.y / self._current_height) / self._widget_scaling - if self.value > 1: - self.value = 1 - if self.value < 0: - self.value = 0 + if self.value > 1: + self.value = 1 + if self.value < 0: + self.value = 0 - self.output_value = self.round_to_step_size(self.from_ + (self.value * (self.to - self.from_))) - self.value = (self.output_value - self.from_) / (self.to - self.from_) + self.output_value = self.round_to_step_size(self.from_ + (self.value * (self.to - self.from_))) + self.value = (self.output_value - self.from_) / (self.to - self.from_) - self.draw(no_color_updates=False) + self.draw(no_color_updates=False) - if self.callback_function is not None: - self.callback_function(self.output_value) + if self.variable is not None: + self.variable_callback_blocked = True + self.variable.set(round(self.output_value) if isinstance(self.variable, tkinter.IntVar) else self.output_value) + self.variable_callback_blocked = False - if self.variable is not None: - self.variable_callback_blocked = True - self.variable.set(round(self.output_value) if isinstance(self.variable, tkinter.IntVar) else self.output_value) - self.variable_callback_blocked = False + if self.callback_function is not None: + self.callback_function(self.output_value) def on_enter(self, event=0): - self.hover_state = True - self.canvas.itemconfig("slider_parts", fill=ThemeManager.single_color(self.button_hover_color, self._appearance_mode), - outline=ThemeManager.single_color(self.button_hover_color, self._appearance_mode)) + if self.state == "normal": + self.hover_state = True + self.canvas.itemconfig("slider_parts", + fill=ThemeManager.single_color(self.button_hover_color, self._appearance_mode), + outline=ThemeManager.single_color(self.button_hover_color, self._appearance_mode)) def on_leave(self, event=0): self.hover_state = False - self.canvas.itemconfig("slider_parts", fill=ThemeManager.single_color(self.button_color, self._appearance_mode), + 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)) def round_to_step_size(self, value): @@ -231,8 +249,8 @@ class CTkSlider(CTkBaseClass): self.draw(no_color_updates=False) - if self.callback_function is not None: - self.callback_function(self.output_value) + # if self.callback_function is not None and not from_variable_callback: + # self.callback_function(self.output_value) if self.variable is not None and not from_variable_callback: self.variable_callback_blocked = True @@ -246,6 +264,12 @@ class CTkSlider(CTkBaseClass): def configure(self, *args, **kwargs): require_redraw = False # some attribute changes require a call of self.draw() at the end + if "state" in kwargs: + self.state = kwargs["state"] + self.set_cursor() + require_redraw = True + del kwargs["state"] + if "fg_color" in kwargs: self.fg_color = kwargs["fg_color"] require_redraw = True diff --git a/examples/complex_example.py b/examples/complex_example.py index c2ef545..f2487b2 100644 --- a/examples/complex_example.py +++ b/examples/complex_example.py @@ -46,30 +46,27 @@ class App(customtkinter.CTk): self.label_1.grid(row=1, column=0, pady=10, padx=10) self.button_1 = customtkinter.CTkButton(master=self.frame_left, - text="CTkButton 1", - fg_color=("gray75", "gray30"), # <- custom tuple-color + text="CTkButton", command=self.button_event) self.button_1.grid(row=2, column=0, pady=10, padx=20) self.button_2 = customtkinter.CTkButton(master=self.frame_left, - text="CTkButton 2", - fg_color=("gray75", "gray30"), # <- custom tuple-color + text="CTkButton", command=self.button_event) self.button_2.grid(row=3, column=0, pady=10, padx=20) self.button_3 = customtkinter.CTkButton(master=self.frame_left, - text="CTkButton 3", - fg_color=("gray75", "gray30"), # <- custom tuple-color + text="CTkButton", command=self.button_event) self.button_3.grid(row=4, column=0, pady=10, padx=20) - self.switch_1 = customtkinter.CTkSwitch(master=self.frame_left) - self.switch_1.grid(row=9, column=0, pady=10, padx=20, sticky="w") + self.label_mode = customtkinter.CTkLabel(master=self.frame_left, text="Appearance Mode:") + self.label_mode.grid(row=9, column=0, pady=0, padx=20, sticky="w") - self.switch_2 = customtkinter.CTkSwitch(master=self.frame_left, - text="Dark Mode", - command=self.change_mode) - self.switch_2.grid(row=10, column=0, pady=10, padx=20, sticky="w") + self.optionmenu_1 = customtkinter.CTkOptionMenu(master=self.frame_left, + values=["Light", "Dark", "System"], + command=self.change_appearance_mode) + self.optionmenu_1.grid(row=10, column=0, pady=10, padx=20, sticky="w") # ============ frame_right ============ @@ -134,25 +131,17 @@ class App(customtkinter.CTk): command=self.progressbar.set) self.slider_2.grid(row=5, column=0, columnspan=2, pady=10, padx=20, sticky="we") - self.slider_button_1 = customtkinter.CTkButton(master=self.frame_right, - height=25, - text="CTkButton", - command=self.button_event) - self.slider_button_1.grid(row=4, column=2, columnspan=1, pady=10, padx=20, sticky="we") + self.switch_1 = customtkinter.CTkSwitch(master=self.frame_right, + text="CTkSwitch") + self.switch_1.grid(row=4, column=2, columnspan=1, pady=10, padx=20, sticky="we") - self.slider_button_2 = customtkinter.CTkButton(master=self.frame_right, - height=25, - text="CTkButton", - command=self.button_event) - self.slider_button_2.grid(row=5, column=2, columnspan=1, pady=10, padx=20, sticky="we") + self.switch_2 = customtkinter.CTkSwitch(master=self.frame_right, + text="CTkSwitch") + self.switch_2.grid(row=5, column=2, columnspan=1, pady=10, padx=20, sticky="we") - self.checkbox_button_1 = customtkinter.CTkButton(master=self.frame_right, - height=25, - text="CTkButton", - border_width=3, # <- custom border_width - fg_color=None, # <- no fg_color - command=self.button_event) - self.checkbox_button_1.grid(row=6, column=2, columnspan=1, pady=10, padx=20, sticky="we") + self.combobox_1 = customtkinter.CTkComboBox(master=self.frame_right, + values=["Value 1", "Value 2"]) + self.combobox_1.grid(row=6, column=2, columnspan=1, pady=10, padx=20, sticky="we") self.check_box_1 = customtkinter.CTkCheckBox(master=self.frame_right, text="CTkCheckBox") @@ -169,16 +158,20 @@ class App(customtkinter.CTk): self.button_5 = customtkinter.CTkButton(master=self.frame_right, text="CTkButton", + border_width=3, # <- custom border_width + fg_color=None, # <- no fg_color command=self.button_event) self.button_5.grid(row=8, column=2, columnspan=1, pady=20, padx=20, sticky="we") # set default values + self.optionmenu_1.set("Dark") + self.button_3.configure(state="disabled", text="Disabled CTkButton") + self.combobox_1.set("CTkCombobox") self.radio_button_1.select() - self.switch_2.select() self.slider_1.set(0.2) self.slider_2.set(0.7) self.progressbar.set(0.5) - self.slider_button_1.configure(state=tkinter.DISABLED, text="Disabled Button") + self.switch_2.select() self.radio_button_3.configure(state=tkinter.DISABLED) self.check_box_1.configure(state=tkinter.DISABLED, text="CheckBox disabled") self.check_box_2.select() @@ -186,11 +179,8 @@ class App(customtkinter.CTk): def button_event(self): print("Button pressed") - def change_mode(self): - if self.switch_2.get() == 1: - customtkinter.set_appearance_mode("dark") - else: - customtkinter.set_appearance_mode("light") + def change_appearance_mode(self, new_appearance_mode): + customtkinter.set_appearance_mode(new_appearance_mode) def on_closing(self, event=0): self.destroy() diff --git a/test/manual_integration_tests/test_widget_states.py b/test/manual_integration_tests/test_states.py similarity index 90% rename from test/manual_integration_tests/test_widget_states.py rename to test/manual_integration_tests/test_states.py index 89c36bb..188aba8 100644 --- a/test/manual_integration_tests/test_widget_states.py +++ b/test/manual_integration_tests/test_states.py @@ -3,7 +3,7 @@ import customtkinter app = customtkinter.CTk() -app.geometry("400x800") +app.geometry("400x900") app.title("CustomTkinter Test") @@ -53,5 +53,10 @@ combobox_1.pack(pady=10, padx=10) button_7 = customtkinter.CTkButton(master=app, text="Disable/Enable combobox_1", command=lambda: change_state(combobox_1)) button_7.pack(padx=20, pady=(10, 20)) +slider_1 = customtkinter.CTkSlider(app) +slider_1.pack(pady=10, padx=10) +button_8 = customtkinter.CTkButton(master=app, text="Disable/Enable slider_1", command=lambda: change_state(slider_1)) +button_8.pack(padx=20, pady=(10, 20)) + app.mainloop()