如何使用 tkinter 更新多个标签
How to update multiple labels with tkinter
我正在尝试在 python 中制作一个秒表,它也将经过的时间以小数小时显示为 worktime
,并将超过 8 小时的任何经过时间转换为 overtime
。
我让秒表部分正常工作(公平地说,我主要模仿教程),但是当我尝试添加额外的小数时,事情就出错了。我尝试了一堆看起来有点合乎逻辑但在运行时出现更多错误的东西,或者我在秒表旁边的标签保持为零,或者在目前的情况下 python 几秒钟后崩溃(我的猜测是三个.after
基本上是以指数方式调用 运行 update()
?)
我想推土机解决方案对我来说只是为我的每个标签制作 update()
函数的副本,我 9/10 确定它会起作用,但这听起来愚蠢地多余。
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:是的,我知道我可以使用时间模块,我只是喜欢我的脚本中简单有趣的数学。
PS2:是的,我知道我现在的秒表计时速度快了 100 倍,这是为了便于测试。我会在它工作时回到1000ms。
感谢@acw1668 的指出,我重新审视了我的代码,并注意到我是如何误解了 .after()
的用法并期望它负责刷新标签,而这一切真的确实是以固定间隔调用 update()
。
重要的部分就是上面两行,在我的“建筑标签”评论下:
stopwatch_label.config(text=hours_string + ':' + minutes_string + ':' + seconds_string)
出于某种原因,我的大脑认为这只是将秒表标签的不同部分合二为一。但是.config()
的核心用法恰恰是改变文字。
所以我所要做的就是将此行复制两次,并更改它以影响我的 worktime
和 overtime
计数器:
worktime_label.config(text='Work time : ' + str(totalWorktime))
overtime_label.config(text=' Overtime : ' + str(overtime))
我还必须在 reset()
和 pause()
中删除它们各自的 .after_cancel()
方法,并且在进行一些更多的外观更改之后,这是完整的功能代码:
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)
counting = False
def reset():
global counting
if counting:
stopwatch_label.after_cancel(update_time)
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')
worktime_label.config(text='Work time : 0')
overtime_label.config(text=' Overtime : 0')
# 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 = round(hours + (minutes / 60), 2)
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}'
# refresh labels with new text content
stopwatch_label.config(text=hours_string + ':' + minutes_string + ':' + seconds_string)
worktime_label.config(text='Work time : ' + str(totalWorktime))
overtime_label.config(text=' Overtime : ' + str(overtime))
global update_time, update_worktime, update_overtime
update_time = stopwatch_label.after(1000, 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 : 0', font=('Arial', 20), anchor="w", width=20)
worktime_label.pack()
overtime_label = tk.Label(text=' Overtime : 0', font=('Arial', 20), anchor="w", width=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()
感谢您的帮助!
我正在尝试在 python 中制作一个秒表,它也将经过的时间以小数小时显示为 worktime
,并将超过 8 小时的任何经过时间转换为 overtime
。
我让秒表部分正常工作(公平地说,我主要模仿教程),但是当我尝试添加额外的小数时,事情就出错了。我尝试了一堆看起来有点合乎逻辑但在运行时出现更多错误的东西,或者我在秒表旁边的标签保持为零,或者在目前的情况下 python 几秒钟后崩溃(我的猜测是三个.after
基本上是以指数方式调用 运行 update()
?)
我想推土机解决方案对我来说只是为我的每个标签制作 update()
函数的副本,我 9/10 确定它会起作用,但这听起来愚蠢地多余。
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:是的,我知道我可以使用时间模块,我只是喜欢我的脚本中简单有趣的数学。
PS2:是的,我知道我现在的秒表计时速度快了 100 倍,这是为了便于测试。我会在它工作时回到1000ms。
感谢@acw1668 的指出,我重新审视了我的代码,并注意到我是如何误解了 .after()
的用法并期望它负责刷新标签,而这一切真的确实是以固定间隔调用 update()
。
重要的部分就是上面两行,在我的“建筑标签”评论下:
stopwatch_label.config(text=hours_string + ':' + minutes_string + ':' + seconds_string)
出于某种原因,我的大脑认为这只是将秒表标签的不同部分合二为一。但是.config()
的核心用法恰恰是改变文字。
所以我所要做的就是将此行复制两次,并更改它以影响我的 worktime
和 overtime
计数器:
worktime_label.config(text='Work time : ' + str(totalWorktime))
overtime_label.config(text=' Overtime : ' + str(overtime))
我还必须在 reset()
和 pause()
中删除它们各自的 .after_cancel()
方法,并且在进行一些更多的外观更改之后,这是完整的功能代码:
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)
counting = False
def reset():
global counting
if counting:
stopwatch_label.after_cancel(update_time)
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')
worktime_label.config(text='Work time : 0')
overtime_label.config(text=' Overtime : 0')
# 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 = round(hours + (minutes / 60), 2)
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}'
# refresh labels with new text content
stopwatch_label.config(text=hours_string + ':' + minutes_string + ':' + seconds_string)
worktime_label.config(text='Work time : ' + str(totalWorktime))
overtime_label.config(text=' Overtime : ' + str(overtime))
global update_time, update_worktime, update_overtime
update_time = stopwatch_label.after(1000, 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 : 0', font=('Arial', 20), anchor="w", width=20)
worktime_label.pack()
overtime_label = tk.Label(text=' Overtime : 0', font=('Arial', 20), anchor="w", width=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()
感谢您的帮助!