Closing a window and opening a new one via a button in Tkinter
I was wondering if there was a way to open a new instance of Toplevel() and close the current one via the press of a button, i.e. close the current window and open a new one. Here is the code in question:
def start(self): self.name = tk.DoubleVar() name_w = tk.Toplevel(root) name_w.wm_title("Enter name") f1 = tk.Frame(name_w) f1.pack() L1 = tk.Label(f1, text="Please enter your name!") L1.grid(row=0, column=0) E1 = tk.Entry(f1, textvariable=self.name) E1.grid(row=1, column=0) N1 = tk.Button(f1, text="Next", command = self.Q1) N1.grid(row=2, column=0)
In this case, I want self.Q1 to be called, while also destroying name_w. Is there anyway to do this? Thanks.
1 Answer 1
Yes, it’s possible. To close an instance of Toplevel simply destroy it. You’ll need to save a reference to the window. In your case I would either have Q1 destroy the window, or make a separate function that calls Q1 and then destroys the window. It all depends on what the main purpose of Q1 is.
def start(self): . self.new_window = name_w . def quit_window(self): self.Q1() self.new_window.destroy()
If you have multiple of these you might need to store the window references in a list or dictionary, but the basic mechanism is the same: use .destroy() to destroy the window.
This isn’t the only way, of course. You could use lambda or functools.partial and a function that accepts the name of the window to destroy, or you could use nested functions, etc.
Python tkinter close window
Last updated: Jun 9, 2023
Reading time · 4 min
# Table of Contents
# How to close the Window in Tkinter
You can use the root.destroy() method to close the Window in Tkinter.
The method destroys all widgets and exits the mainloop.
Copied!from tkinter import Tk, ttk root = Tk() frm = ttk.Frame(root, padding=10) frm.grid() ttk.Label(frm, text="bobbyhadz.com").grid(column=0, row=0) # 👇️ Close tkinter window when the button is clicked ttk.Button(frm, text="Close Window", command=root.destroy).grid(column=1, row=0) root.mainloop()
We used the Tk() class to create a new top-level widget and stored the result in the root variable.
We then used the ttk.Button() class to create a Button widget.
The command keyword argument we passed to the ttk.Button class is a method that gets called when the button is clicked.
Copied!ttk.Button(frm, text="Close Window", command=root.destroy).grid(column=1, row=0)
The root.destroy() method destroys all widgets and exits the mainloop.
Any code after the call to root.mainloop() will still run, however, attempts to access any widgets after calling root.destroy() will fail because the widgets no longer exist.
Here is a simplified version without a Label widget.
Copied!from tkinter import Tk, ttk root = Tk() ttk.Button( root, text="Close Tkinter Window", command=root.destroy ).pack() root.mainloop()
As shown in the short clip, the root.destroy() method exits, stops the mainloop() and closes the Tkinter program completely.
After calling the method, the window and all widgets are destroyed.
You can also define a custom function that closes the Tkinter window.
Copied!from tkinter import Tk, ttk root = Tk() frm = ttk.Frame(root, padding=10) frm.grid() ttk.Label(frm, text="bobbyhadz.com").grid(column=0, row=0) # 👇️ defining a custom function def quit_tk(): root.destroy() print('Tkinter window closed ✅') # 👇️ Close tkinter window when the button is clicked ttk.Button(frm, text="Close Window", command=quit_tk).grid(column=1, row=0) root.mainloop()
The quit_tk() function is called when the user clicks the «Close Window» button.
Defining a custom wrapper function enables you to run some custom code after closing the Tkinter window.
The example simply prints a message to the terminal.
If you want to close the Tkinter window and end the execution of the Python program, you have to call:
- root.destroy() — destroys all widgets and closes the main loop.
- exit() — ends the execution of the Python program.
Copied!from tkinter import Tk, ttk root = Tk() frm = ttk.Frame(root, padding=10) frm.grid() ttk.Label(frm, text="bobbyhadz.com").grid(column=0, row=0) # 👇️ defining a custom function def quit_tk(): # 1) destroys all widgets and closes the main loop root.destroy() # 2) ends the execution of the Python program exit() # 👇️ Close tkinter window when the button is clicked ttk.Button(frm, text="Close Window", command=quit_tk).grid(column=1, row=0) root.mainloop()
If you have any code that is placed after the root.mainloop() line and you close the window with root.destroy() method, the code will still run.
Copied!from tkinter import Tk, ttk root = Tk() ttk.Button( root, text="Close Tkinter Window", command=root.destroy ).pack() root.mainloop() print('bobbyhadz.com')
However, you wouldn’t be able to access any widgets after calling root.destroy .
# Using root.destroy vs root.quit in Tkinter
If you need to be able to interact with the widgets after, you have to use the root.quit() method.
When the root.quit() method is used, the interpreter is still intact, as are all the widgets.
In other words, you can still interact with the widgets after calling root.quit() .
Here is a simple example of using the root.quit() method instead of root.destroy .
Copied!from tkinter import Tk, ttk root = Tk() ttk.Label(root, text="bobbyhadz.com").grid(column=0, row=0) entry = ttk.Entry(root) entry.grid(row=0, column=1) # 👇️ Using root.quit() def quit_tk(): root.quit() ttk.Button(root, text="Quit", command=quit_tk).grid(row=0, column=2) root.mainloop() print(entry.get())
If you look at your terminal after clicking the Quit button, you can see that the entry.get() line has run successfully.
The widgets are still accessible even after calling root.quit() .
This is not the case when you use the root.destroy() method.
I’ll make the following change in the code snippet.
Copied!# 👇️ Using root.quit() def quit_tk(): root.quit()
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()
Hey Matt. Thanks for having a clear question, and a clean and simple code example to accompany. Could you also make sure to include the traceback (crash) in the future when your code is «not working»? That will also help people almost instantly figure out what part of your code is broken. Obviously in this case, your code sample is so small that its easy to identify, but it might really help you get answers in the future on harder situations.
For anyone not immediately seeing the problem, the error is TypeError: close_window() missing 1 required positional argument: ‘root’ . This means that there was no argument passed to the callback close_window , as there never is for command= functions. Bound event callbacks do get an argument — the event object.
6 Answers 6
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()
def close_window(): window.destroy()
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 .