I have tried every way of closing a tkinter window that I could find on the internet. The only reason I am asking this question, even though it has been asked many times already, is that I still cannot make it work.
Basically, I'm making a simple 'countdown' game (like the TV show), which involves a large 30-second tkinter 'timer'. The number ticks down correctly, but the program won't continue unless the user manually CLOSES the window. Clearly, this defeats the purpose of the timer in the first place, but how can I make it close automatically when I want it to?
Here is a very simple example that doesn't work:
# python 3.5.2
from tkinter import *
root = Tk()
root.title("Test")
root.mainloop()
# root.destroy() / root.quit() <== neither of these are effective
print("The window has now been closed") ## not unless the user crosses it off!
I tried using the 'after' method. First I tried 'root.after(30000, destroy())' and then, just in case, I tried 'root.after(30000, window_closer)' after creating a procedure 'window_closer()' that DOES the destroy command. I'm assuming that made no difference at all. Which is a shame, because I'd succeeded, it would have been ideal.
I also tried creating a frame and then 'destroying' the frame, but although it may disable the widgets, it doesn't actually CLOSE the window (as in, cross it off). When I tried 'root.quit()', nothing happened. With 'root.destroy()', I got the error message 'tkinter.TclError: can't invoke "destroy" command: application has been destroyed'. Apparently that has something to do with the mainloop(), but I don't really get it despite having googled it, and looked at other peoples' answers.
Am I missing something? Any help would be much appreciated!
In your code, you're trying to run code after calling mainloop
. mainloop
won't return until the window has been destroyed, so any attempt after that to modify the window will fail with the "application has been destroyed" error.
You are correct that you need to use after
to schedule the destruction, and you need to use destroy
to cause the destruction. The important thing to remember about after
is that you must give it a reference to a function. If you need to pass arguments to the function, those can be specified as additional arguments in the after
call.
In other words:
root.after(1000, root.destroy())
is exactly the same as this:
result = root.destroy()
root.after(1000, result)
Instead, you need to pass destroy
without the parenthesis. In the absolute simplest case, your program would look like this:
import tkinter as tk
root = tk.Tk()
root.after(10000, root.destroy)
root.mainloop()
If you want to update a countdown clock, you can call your own function every second, and destroy the window when the countdown winds down.
Here's an example:
import tkinter as tk
def countdown(time):
if time == -1:
root.destroy()
else:
if time == 0:
label.configure(text="BOOM")
else:
label.configure(text="time remaining: %d seconds" % time)
root.after(1000, countdown, time-1)
root = tk.Tk()
label = tk.Label(root, width=30)
label.pack(padx=20, pady=20)
countdown(10)
root.mainloop()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With