Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exit a tkinter window after a certain time period?

Tags:

python

tkinter

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!

like image 738
Parallax Sugar Avatar asked Feb 05 '23 00:02

Parallax Sugar


1 Answers

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()
like image 94
Bryan Oakley Avatar answered Feb 08 '23 15:02

Bryan Oakley