'How to update multiple labels with tkinter

I am trying to make a stopwatch in python that also shows the elapsed time in decimal hours as worktime, and also converts whatever time elapsed over 8 hrs into overtime.

I got the stopwatch part functional (to be fair I mostly mimicked tutorials), but when I tried to add the additional decimal, then things got wrong. I tried a bunch of stuff that somewhat looked logical but got either more errors at runtime, or my labels aside the stopwatch stayed at zero, or in the present case python crashes after a few seconds (my guess is that the three .after are basically calling running update() exponentially?)

I suppose the bulldozer solution would be for me to just make duplicates of the update() function for each of my labels, I'm 9/10 sure it will work, but that just sounds stupidly redundant.

import tkinter as tk

### Vars
counting = False
hours, minutes, seconds = 0, 0, 0
totalWorktime, overtime = 0, 0

### Funcs

def start():
    global counting
    if not counting:
        update()
        counting = True

def pause():
    global counting
    if counting:
        stopwatch_label.after_cancel(update_time)
        worktime_label.after_cancel(update_worktime)
        overtime_label.after_cancel(update_overtime)
        counting = False

def reset():
    global counting
    if counting:
        stopwatch_label.after_cancel(update_time)
        worktime_label.after_cancel(update_worktime)
        overtime_label.after_cancel(update_overtime)
        counting = False
    global hours, minutes, seconds, totalWorktime, overtime
    hours, minutes, seconds = 0, 0, 0
    totalWorktime, overtime = 0, 0
    stopwatch_label.config(text='00:00:00')

# update stopwatch label
def update():
    global hours, minutes, seconds, totalWorktime, overtime
    # time counting system
    seconds += 1
    if seconds ==60:
        minutes += 1
        seconds = 0
    if minutes == 60:
        hours += 1
        minutes = 0
    totalWorktime = hours + (minutes / 60)
    if totalWorktime > 8:
        overtime = totalWorktime - 8
    # format with zero padding
    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}'
    # building label
    stopwatch_label.config(text=hours_string + ':' + minutes_string + ':' + seconds_string)
    global update_time, update_worktime, update_overtime
    update_time = stopwatch_label.after(10, update)
    update_worktime = worktime_label.after(10, update)
    update_overtime = overtime_label.after(10, update)

### UI
# main window
root = tk.Tk()
root.geometry('512x256')
root.title('Worktime Stopwatch')

# time display
stopwatch_label = tk.Label(text='00:00:00', font=('Arial', 80))
stopwatch_label.pack()
worktime_label = tk.Label(text='Work time : ' + str(totalWorktime), font=('Arial', 20))
worktime_label.pack()
overtime_label = tk.Label(text='Overtime : ' + str(overtime), font=('Arial', 20))
overtime_label.pack()

# buttons
start_button = tk.Button(text='Start', height=4, width=8, font=('Arial', 20), command=start)
start_button.pack(side=tk.LEFT)
pause_button = tk.Button(text='Pause', height=4, width=8, font=('Arial', 20), command=pause)
pause_button.pack(side=tk.LEFT)
reset_button = tk.Button(text='Reset', height=4, width=8, font=('Arial', 20), command=reset)
reset_button.pack(side=tk.LEFT)

# run
root.mainloop()

PS: Yes I know I could have used the time module, I just like simple funny math in my scripts.
PS2: Yes I know my current stopwatch counts time 100 times too fast, that's to make it easy to test. I will get back to 1000ms when it works.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source