Home > Back-end >  Tkinter stopwatch stops with 1 second delay
Tkinter stopwatch stops with 1 second delay

Time:07-13

When you press "reset" button, the stopwatch is supposed to stop and reset, but instead it sets digits to zero, then adds one more second and ends up with 00:00:01.

The same with "stop" button. F.e. if we press stop at 00:05, it stops with 00:06. Plus one second every time. But sometimes you can click at the right moment, at the very beginning of the current second so it won't happen.

I tried after_cancel, didn't help.

It's impossible to run debugging in VScode because break points block buttons while the time is going, so I can't trigger the function.

I followed several tutorials and every time I implement pieces of their code, I get this issue.

Why does it happen? Where this 1 second comes from and how to fix?

from tkinter import *

root = Tk()

switch = False

def start():
    global switch
    switch = True

def stop():
    global switch
    switch = False


# Stopwatch variables
seconds = 0
minutes = 0
hours = 0

# Stopwatch functions

def stopwatch_update():
            global seconds, minutes, hours
            seconds  = 1
            if seconds == 60:
                minutes  = 1
                seconds = 0
            if minutes == 60:
                hours  = 1
                minutes = 0
            
            hours_string = f'{hours}' if hours > 9 else f'0{hours}'
            minutes_string = f'{minutes}' if minutes > 9 else f'0{minutes}'
            seconds_string = f'{seconds}' if seconds > 9 else f'0{seconds}'

            stopwatch_label.config(text = hours_string   ':'   minutes_string   ':'   seconds_string)
            if switch:
                stopwatch_label.after(1000, stopwatch_update)

def stopwatch_func(command):
    if command == 'start':
        start()
        stopwatch_start.config(state='disabled')
        stopwatch_stop.config(state='normal')
        stopwatch_reset.config(state='normal')
        stopwatch_update()


    if command == 'stop':
        stopwatch_start.config(state='normal')
        stopwatch_stop.config(state='disabled')
        stop()

    if command == 'reset':
        stopwatch_start.config(state='normal')
        stopwatch_stop.config(state='disabled')
        stop()
        global hours, minutes, seconds
        hours, minutes, seconds = 0, 0, 0
        stopwatch_label.config(text='00:00:00')

                

# Stopwatch components
stopwatch_label = Label(root, font='calibri 20', text='Stopwatch')
stopwatch_label.pack()
stopwatch_start = Button(root, text='Start', command=lambda: stopwatch_func('start'))
stopwatch_start.pack()
stopwatch_stop = Button(root, text='Stop', state='disabled',command=lambda:stopwatch_func('stop'))
stopwatch_stop.pack()
stopwatch_reset = Button(root, text='Reset', state='disabled', command=lambda:stopwatch_func('reset'))
stopwatch_reset.pack()


mainloop()

CodePudding user response:

Defined a variable for stopwatch_label.after(1000, stopwatch_update) and now everything works fine.

The end of stopwatch_update():

if switch:
          global stopwatch_after
          stopwatch_after = stopwatch_label.after(1000, stopwatch_update)

stopwatch_func(command) is also updated for "stop" and "reset" commands:

if command == 'stop':
        stopwatch_start.config(state='normal')
        stopwatch_stop.config(state='disabled')
        stop()
        stopwatch_label.after_cancel(stopwatch_after)

if command == 'reset':
        stopwatch_start.config(state='normal')
        stopwatch_stop.config(state='disabled')
        stop()
        global hours, minutes, seconds
        hours, minutes, seconds = 0, 0, 0
        stopwatch_label.config(text='00:00:00')
        stopwatch_label.after_cancel(stopwatch_after)
  • Related