9

I want to set a label in Tkinter using my countdown timer function. Right now all it does is set the lable to "10" once 10 is reached and I don't really understand why. Also, even if I have the timer print to a terminal instead the "Time's up!" bit never prints.

import time
import tkinter as tk

class App():
    def __init__(self):
        self.root = tk.Tk()
        self.label = tk.Label(text="null")
        self.label.pack()
        self.countdown()
        self.root.mainloop()

    # Define a timer.
    def countdown(self):
        p = 10.00
        t = time.time()
        n = 0
        # Loop while the number of seconds is less than the integer defined in "p"
        while n - t < p: 
            n = time.time()
            if n == t + p:
                self.label.configure(text="Time's up!")
            else:
                self.label.configure(text=round(n - t))

app=App()
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
Ryan Hasse
  • 253
  • 1
  • 4
  • 15
  • here's a [code example of a countdown implemented using Tkinter](https://gist.github.com/zed/1951815) – jfs Mar 03 '15 at 09:15

1 Answers1

13

Tkinter already has an infinite loop running (the event loop), and a way to schedule things to run after a period of time has elapsed (using after). You can take advantage of this by writing a function that calls itself once a second to update the display. You can use a class variable to keep track of the remaining time.

import Tkinter as tk

class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.label = tk.Label(self, text="", width=10)
        self.label.pack()
        self.remaining = 0
        self.countdown(10)

    def countdown(self, remaining = None):
        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:
            self.label.configure(text="time's up!")
        else:
            self.label.configure(text="%d" % self.remaining)
            self.remaining = self.remaining - 1
            self.after(1000, self.countdown)

if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • That explains a lot, thank you. I was wondering why it only updates once the last item is reached even after I rewrote it a few different ways. – Ryan Hasse May 15 '12 at 11:49
  • 2
    @RyanHasse: the display only updates when Tkinter can respond to events that tell it to update the display. These events only get processed by the event loop. If you have your own loop, it will starve the event loop, preventing redraw requests from happening. – Bryan Oakley May 15 '12 at 12:54