0

I have this timer program in python with a Tkinter GUI. I am able to run the timer user inputs, but I am having trouble pausing or stopping the timer from a tkinter button. I tried creating a variable that changes when the stop button press to initiate time.sleep() in my if statement, but no luck. Any ideas?

from tkinter import Tk, Label, StringVar
from tkinter.ttk import Button, Entry

class Timer:
    def __init__(self, master):
        self.seconds = 0
        self.f = False
        self.time = StringVar()
        self.time_label = Label(master, relief='flat', font=("Cambria", 20),
                            textvariable=self.time)

        self.hr = StringVar()
        self.hr_label = Label(master, text='Hours:').grid(row=1, column=1, padx=5, pady=1)
        self.entry_hr = Entry(master, textvariable=self.hr, width=4)
        self.entry_hr.grid(row=1, column=2)

        self.mins = StringVar()
        self.min_label = Label(master, text='Minutes:').grid(row=2, column=1, padx=5, pady=1)
        self.entry_min = Entry(master, textvariable=self.mins, width=4)
        self.entry_min.grid(row=2, column=2)

        self.secs = StringVar()
        self.secs_label = Label(master, text='Seconds:').grid(row=3, column=1, padx=5, pady=1)
        self.entry_sec = Entry(master, textvariable=self.secs, width=4)
        self.entry_sec.grid(row=3, column=2)

        self.time.set('00:00:00')
        self.start_button = Button(master, text='Start')
        self.start_button.bind('<Button-1>', self.start_countdown)
        self.stop_button = Button(master, text='Stop')

        self.time_label.grid(row=0, columnspan=4, padx=30, pady=10)
        self.start_button.grid(row=4, columnspan=4, pady=(10,20))
        self.stop_button.grid(row=5, columnspan=4, pady=(10,20))

    def set_time(self, hours, minutes, seconds):
        self.seconds = hours * 3600 + minutes * 60 + seconds
        self.time.set(self.format_time(self.seconds))

    def start_countdown(self, event):
        f = False
        h = self.entry_hr.get()
        m = self.entry_min.get()
        s = self.entry_sec.get()
        h,m,s = map(lambda x: int(x) if x else 0, (h,m,s))
        self.set_time(h,m,s)
        self.countdown()

    def stop(self):
        global f
        f= True

    def countdown(self):
        if self.seconds <= 0:
        return
        else: 
            self.end_label = Label( text ="Time's up")
        if self.f == True:
            time.sleep()
        self.time.set(self.format_time(self.seconds))
        self.seconds -= 1
        self.time_label.after(1000, self.countdown)

    def format_time(self, seconds):
        h = seconds // 3600
        m = (seconds - h*3600) // 60
        s = seconds - h*3600 - m*60
        return '{:0>2}:{:0>2}:{:0>2}'.format(h,m,s)

if __name__ == '__main__':
    root = Tk()
    timer = Timer(root)
    root.mainloop()

1 Answer 1

2

First of all your Button widget self.stop_button doesn't have a command or binding associated with it, so it doesn't actually do anything.

Secondly, even if it did call the function you're changing the value of the global variable f but in your if statement you're referencing the local variable self.f (Timer.f).

Thirdly, you're not calling time.sleep() correctly, it requires a value in seconds to sleep for.

And fourthly, time.sleep() would only delay the function from running for the period of time you specify and would eventually cause the timer to start ticking down again.

Instead, you should do something like the below (after associating the Button widget to the function self.stop()):

def stop(self):
    self.f = True

def countdown(self):
    if self.f == False:
        print(self.f)
        if self.seconds <= 0:
            return
        else: 
            self.end_label = Label( text ="Time's up")
        self.time.set(self.format_time(self.seconds))
        self.seconds -= 1
        self.time_label.after(1000, self.countdown)

This will mean that every time we cycle through the function the first thing we do is check whether self.f is False, if it isn't then the timer stops where it is.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.