Search code examples
pythontkintertimercountdown

Timer never updates when using `after`


So I'm trying to make a countdown counter on tkinter that starts from 03:00 minutes and ends on 00:00, actively updated every second. At first I used a while loop with time.sleep() but it freezed my tkinter, so I tried to use tkinter after() method but without any success. What I'm trying to do is to start a timer from 03:00 minutes, goes down - 02:59, 02:58, 02:57,....,00:00 the timer is being represented using a tk.StringVar and should start just when the tkinter window open

This code I wrote raises a maximum recursion depth exception:

class BoggleGUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Boggle Game")
        self.root.resizable(False, False)

        self.__sec = tk.StringVar()
        self.__sec_entry = tk.Entry(self.root, textvariable=self.__sec,
                                    width=2, font="Helvetica 14")
        self.__sec_entry.place(x=220, y=12.5)
        self.__sec.set("00")

        self.__mins = tk.StringVar()
        self.__mins_entry = tk.Entry(self.root, textvariable=self.__mins,
                                     width=2, font="Helvetica 14")
        self.__mins_entry.place(x=190, y=12.5)
        self.__mins.set("03")

        self.countdown_timer()

    def countdown_timer(self):
        times = int(self.__mins.get()) * 60 + int(self.__sec.get())
        if times > -1:
            minute, second = divmod(times, 60)
            self.__mins.set("{0:2d}".format(minute))
            self.__sec.set("{0:2d}".format(second))

            self.root.update()

            if times == 0:
                self.__sec.set('00')
                self.__mins.set('00')
            times -= 1
        self.root.after(1000, self.countdown_timer)

Solution

  • You need to move times =- 1 above:

                minute, second = divmod(times, 60)
                self.__mins.set("{0:2d}".format(minute))
                self.__sec.set("{0:2d}".format(second))
    

    otherwise the update of the time does not happen and realign self.root.after(1000, self.countdown_timer)

    Change the function to this and it will work:

        def countdown_timer(self):
            times = int(self.__mins.get()) * 60 + int(self.__sec.get())
            if times > 0:
                times -= 1
    
                minute, second = divmod(times, 60)
                self.__mins.set("{0:2d}".format(minute))
                self.__sec.set("{0:2d}".format(second))
    
                self.root.update()
    
                if times == 0:
                    self.__sec.set('00')
                    self.__mins.set('00')
                self.root.after(1000, self.countdown_timer)
    

    I have edited the response, also change if times > -1: to if times > 0: for when it reaches zero, otherwise goes negative.