1

Why does my tkinter Button stays in the "sunken" relief after I press it?

import tkinter
from tkinter import messagebox as msgbox 

class GUI(object):
    def __init__(self):
        self.root = tkinter.Tk()
        self.root.geometry("200x200")
        self.root.title("Test")


        self.testButton = tkinter.Button(self.root, text="Click Me!")
        self.testButton.bind("<Button-1>", self.click)
        self.testButton.bind("<ButtonRelease-1>", self.release)
        self.testButton.pack()

    def release(self, event):
        event.widget.config(relief=tkinter.RAISED)

    def click(self, event):
        result =  msgbox.askokcancel("Continue?", "Do you want to continue?")
        if result:
            print("Okay")
        else:
            print("Well then . . .")
        print(event.widget.cget("relief"))
        print()

if __name__ == "__main__":
    test = GUI()
    test.root.mainloop()

The console shows that the relief is "raised" but on the GUI it stays in the "sunken" relief , why? The GUI after pressing the Button

Lyzeum
  • 33
  • 1
  • 4
  • 1
    Edit your post and place a file, do not put an image to show your code. – eyllanesc Apr 11 '17 at 18:52
  • I can't test it because I don't feel like retyping your code, but I'd guess if you used the `command` argument instead of `bind` it would work like you want: `tkinter.Button(root, text="click me", command=self.click)`. You would also need to remove 'event' from the arguments for the click method. Post the code as text next time. – Novel Apr 11 '17 at 19:12
  • @Jonathan this would fix the problem but is there a way to keep the bind? – Lyzeum Apr 11 '17 at 19:22
  • Yes: bind to "". Include all the needed imports in your code next time. Your example should be runnable. – Novel Apr 11 '17 at 19:42
  • @Jonathan did you test it? It still stays in the sunken relief. I edited the question , thank you :) – Lyzeum Apr 11 '17 at 19:55
  • I did test it and it says 'raised' and the button looks raised. If it doesn't work for you you could try adding `self.root.update()` as the first line in your click method. – Novel Apr 11 '17 at 20:12

1 Answers1

3

Your callback is printing "raised" because your code is run before the default button bindings, so the button relief is in fact raised at the point in time when your function is called.

I'm pretty sure this is what is causing the button to stay sunken:

  1. you click on the button, and a dialog appears. At this point the button is raised because tkinter's default binding has not yet had a chance to run 1, and it is the default bindings which cause the button to appear sunken
  2. a dialog appears, which steals the focus from the main window.
  3. you click and release the button to click on the dialog. Because the dialog has stolen the focus, this second release event is not passed to the button
  4. at this point the processing of the original click continues, with control going to the default tkinter binding for a button click.
  5. the default behavior causes the button to become sunken
  6. at this point, your mouse button is not pressed down, so naturally you can't release the button. Because you can't release the button, the window never sees a release event.
  7. Because the button never sees a button release event, the button stays sunken

1 For a description of how tkinter handles events, see this answer: https://stackoverflow.com/a/11542200/7432. The answer is focused on keyboard events, but the same mechanism applies to mouse buttons.

Community
  • 1
  • 1
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685