Search code examples
pythontkintertkinter-button

The relief of a button isn't having any effect on its appearance in tkinter


I've been working on an autoclicker utilizing tkinter for the gui. I noticed that there isn't any clear way to tell if the autoclicker is toggled or not, so I tried adding a relief to the toggle button. However, the relief isn't affecting the button's appearance at all - it looks the same without relief and with a relief.

Initially the button's relief attribute is set to raised. In the start_autoclicker function (which runs the actual autoclicker), the line self.start_stop_button.configure(relief='sunken') runs before the autoclicker starts. In the toggle_autoclicker function, located below self.running = False is self.start_stop_button.configure(relief='raised').

Clicking the button works properly, but the relief does not change the appearance. I'm on macOS, here are two screenshots for comparison:

raised raised button, looks like default relief

sunken sunked button, looks like default relief

Some code for reference:

The toggle button:

self.start_stop_button = tk.Button(self, text="Toggle", command=self.toggle_autoclicker, relief="raised")
self.start_stop_button.grid(row=2, column=2, sticky="w", padx=(0, 0), pady=(0, 30))

toggle_autoclicker:

    def toggle_autoclicker(self):
        if not self.running:
            try:
                delay = float(self.click_delay_var.get())
                if delay < 0:
                    raise ValueError
                self.running = True
                self.start_autoclicker()
            except ValueError:
                messagebox.showerror("Invalid Interval", "Please enter a click interval greater than zero.")
        else:
            self.running = False
            self.start_stop_button.configure(relief='raised')
            print("+") # for debug

start_autoclicker:

    def start_autoclicker(self):

        if self.key_var.get() == "" and self.mb == "KEY":
            self.running = False
            messagebox.showerror("Invalid Key","Please enter an alphanumeric character or symbol found on your device's keyboard.")
            return
        else:
            self.start_stop_button.configure(relief='sunken')
            print("-") # for debug

        def autoclick():
            while self.running:
                delay = float(self.click_delay_var.get())
                if self.mb == "LMB":
                    self.mouse_controller.click(Button.left, 1)
                elif self.mb == "RMB":
                    self.mouse_controller.click(Button.right, 1)
                elif self.mb == "KEY":
                    self.keyboard_controller.press(self.key_var.get())
                    self.keyboard_controller.release(self.key_var.get())
                time.sleep(delay)

        self.autoclicker_thread = threading.Thread(target=autoclick)
        self.autoclicker_thread.start()

I've done a bit of troubleshooting, but ultimately could not find much information. Please let me know if this post isn't clear enough or lacks needed info, and thanks for taking the time to read this.


Solution

  • If you change from the standard to the ttk button you can achieve this behavior with:

    self.start_stop_button.state(['pressed']) to "press" or self.start_stop_button.state(['!pressed']) to "release".

    To check the state use self.start_stop_button.instate(['pressed'])

    But note, that the button can not be clicked if you set the state to pressed! Therefore i recommend rather changing the button text from "Start" to "Stop" instead so the button remains usable:

    Instead of changing the relief self.start_stop_button.configure(relief='sunken') you can change the Button text and if you want also the color self.start_stop_button.configure(text='Start', bg='green')