[python] How to close a Tkinter window by pressing a Button?

Write a GUI application with a button labeled "Good-bye". When the Button is clicked, the window closes.

This is my code so far, but it is not working. Can anyone help me out with my code?

from Tkinter import *

window = Tk()

def close_window (root): 
    root.destroy()

frame = Frame(window)
frame.pack()
button = Button (frame, text = "Good-bye.", command = close_window)
button.pack()

window.mainloop()

This question is related to python tkinter

The answer is


from tkinter import *

def close_window():
    import sys
    sys.exit()

root = Tk()

frame = Frame (root)
frame.pack()

button = Button (frame, text="Good-bye", command=close_window)
button.pack()

mainloop()

You can use lambda to pass a reference to the window object as argument to close_window function:

button = Button (frame, text="Good-bye.", command = lambda: close_window(window))

This works because the command attribute is expecting a callable, or callable like object. A lambda is a callable, but in this case it is essentially the result of calling a given function with set parameters.

In essence, you're calling the lambda wrapper of the function which has no args, not the function itself.


from tkinter import *

window = tk()
window.geometry("300x300")

def close_window (): 

    window.destroy()

button = Button ( text = "Good-bye", command = close_window)
button.pack()

window.mainloop()

You could create a class that extends the Tkinter Button class, that will be specialised to close your window by associating the destroy method to its command attribute:

from tkinter import *

class quitButton(Button):
    def __init__(self, parent):
        Button.__init__(self, parent)
        self['text'] = 'Good Bye'
        # Command to close the window (the destory method)
        self['command'] = parent.destroy
        self.pack(side=BOTTOM)

root = Tk()
quitButton(root)
mainloop()

This is the output:

enter image description here


And the reason why your code did not work before:

def close_window (): 
    # root.destroy()
    window.destroy()

I have a slight feeling you might got the root from some other place, since you did window = tk().

When you call the destroy on the window in the Tkinter means destroying the whole application, as your window (root window) is the main window for the application. IMHO, I think you should change your window to root.

from tkinter import *

def close_window():
    root.destroy()  # destroying the main window

root = Tk()
frame = Frame(root)
frame.pack()

button = Button(frame)
button['text'] ="Good-bye."
button['command'] = close_window
button.pack()

mainloop()

You can associate directly the function object window.destroy to the command attribute of your button:

button = Button (frame, text="Good-bye.", command=window.destroy)

This way you will not need the function close_window to close the window for you.


With minimal editing to your code (Not sure if they've taught classes or not in your course), change:

def close_window(root): 
    root.destroy()

to

def close_window(): 
    window.destroy()

and it should work.


Explanation:

Your version of close_window is defined to expect a single argument, namely root. Subsequently, any calls to your version of close_window need to have that argument, or Python will give you a run-time error.

When you created a Button, you told the button to run close_window when it is clicked. However, the source code for Button widget is something like:

# class constructor
def __init__(self, some_args, command, more_args):
    #...
    self.command = command
    #...

# this method is called when the user clicks the button
def clicked(self):
    #...
    self.command() # Button calls your function with no arguments.
    #...

As my code states, the Button class will call your function with no arguments. However your function is expecting an argument. Thus you had an error. So, if we take out that argument, so that the function call will execute inside the Button class, we're left with:

def close_window(): 
    root.destroy()

That's not right, though, either, because root is never assigned a value. It would be like typing in print(x) when you haven't defined x, yet.

Looking at your code, I figured you wanted to call destroy on window, so I changed root to window.