Counter down timer - When my start button toggles to pause and resume... clicking on pause or resume does not work

26 Views Asked by At

Counter down timer - When my start button toggles to pause and resume... clicking on pause or resume does not work. Code below:

from tkinter import *
import time
import winsound

class Stopwatch:
    def __init__(self):
        self.root = Tk()
        self.root.title("Countdown Timer")
        self.root.geometry("600x300")
        self.root.resizable(width=True, height=True)  # Allow resizing
        self.t = StringVar()
        self.t.set("00:00:00")
        self.label = Label(self.root, textvariable=self.t, font=("Times 40 bold"), bg="grey")
        self.label.place(x=160, y=10)

        # Entry widgets for hours, minutes, and seconds
        self.hours_var = StringVar()
        self.minutes_var = StringVar()
        self.seconds_var = StringVar()

        self.hours_entry = Entry(self.root, textvariable=self.hours_var, width=5, font=("Times 12 bold"))
        self.minutes_entry = Entry(self.root, textvariable=self.minutes_var, width=5, font=("Times 12 bold"))
        self.seconds_entry = Entry(self.root, textvariable=self.seconds_var, width=5, font=("Times 12 bold"))

        self.hours_entry.place(x=100, y=120)
        self.minutes_entry.place(x=200, y=120)
        self.seconds_entry.place(x=300, y=120)

        self.start_button_text = StringVar()
        self.start_button_text.set("Start")
        self.start_button = Button(self.root, textvariable=self.start_button_text, command=self.toggle_start, font=("Times 12 bold"), bg="green")
        self.start_button.place(x=120, y=200)

        self.bt2 = Button(self.root, text="Stop", command=self.stop_timer, font=("Times 12 bold"), bg="red")
        self.bt3 = Button(self.root, text="Reset", command=self.reset_timer, font=("Times 12 bold"), bg="orange")
        self.bt4 = Button(self.root, text="Exit", command=self.close, font=("Times 12 bold"), bg="yellow")

        self.bt2.place(x=220, y=200)
        self.bt3.place(x=320, y=200)
        self.bt4.place(x=420, y=200)

        self.root.configure(bg='black')
        self.counting = False
        self.paused = False
        self.end_time = 0
        self.sound_start = "start.wav"
        self.sound_end = "end.wav"
        
    # toggling the start, pause, and resume button
    def toggle_start(self):
        if not self.counting:
            self.counting = True
            self.start_button_text.set("Pause")
            self.end_time = self.get_time_seconds()
            self.timer()
        else:
            if not self.paused:
                self.paused = True
                self.start_button_text.set("Resume")
            else:
                self.paused = False
                self.start_button_text.set("Pause")
                remaining_time = self.end_time - time.time()
                self.end_time = time.time() + remaining_time
                self.timer()
                
    def stop_timer(self):
        self.counting = False
        self.paused = False
        self.start_button_text.set("Start")

    def reset_timer(self):
        self.counting = False
        self.paused = False
        self.t.set("00:00:00")
        self.hours_var.set("")
        self.minutes_var.set("")
        self.seconds_var.set("")
        self.start_button_text.set("Start")

            
    def close(self):
        self.root.destroy()

    def timer(self):
        if self.counting:
            remaining_time = self.end_time - time.time()
            if remaining_time <= 0:
                self.counting = False
                self.paused = False
                self.t.set("00:00:00")
                winsound.PlaySound(self.sound_end, winsound.SND_FILENAME)
                self.start_button_text.set("Start")
            else:
                self.t.set(self.format_time(remaining_time))
                self.root.after(1000, self.timer)
        else:
            self.end_time = self.get_time_seconds()

    def get_time_seconds(self):
        try:
            h = int(self.hours_var.get())
            m = int(self.minutes_var.get())
            s = int(self.seconds_var.get())

            if h < 0 or m < 0 or s < 0:
                raise ValueError("Invalid input. Time values cannot be negative.")

            return time.time() + h * 3600 + m * 60 + s
        except ValueError as e:
            print(f"Error: {e}")
            return -1

    def format_time(self, seconds):
        h, remainder = divmod(seconds, 3600)
        m, s = divmod(remainder, 60)
        return f"{int(h):02d}:{int(m):02d}:{int(s):02d}"

if __name__ == "__main__":
    a = Stopwatch()
    a.root.mainloop()

Expected: When I click on start, Then timer should start and the start button should turn to "pause"

When I click on "pause" Then the timer should pause and the "pause" button should turn to "resume"

When I click on "resume" Then the timer should continue and the "resume" button should turn to "pause".

And the circle between pause and resume continues...

Actual result: When I click on start, Then timer starts and the start button turns to "pause"

When I click on "pause" Then the timer does not pause but the "pause" button turns to "resume"

When I click on "resume" Then the timer is not affected but the "resume" turn to "pause".

And the circle between pause and resume continues...

0

There are 0 best solutions below