#user-interface #tkinter #while-loop #timer
Вопрос:
Я успешно создал функцию, которая выводит (как print() ) время секундомера от 0 до 5 секунд.
Я хочу использовать Tkinter для отображения вывода секундомера в окне ввода при нажатии кнопки «Пуск». По какой-то причине, когда вы нажимаете «Пуск», он просто загружается в течение 5 секунд, а затем отображает только последний вывод (5,0 сек).
Почему он не показывает результат, динамически изменяющийся от 0,0 до 5,0 сек? Я прилагаю код сюда — я не могу понять, почему это не работает…
from tkinter import *
import time
win = Tk() # creating a window instance
win.title('stopwach')
def start_timer():
"""begin timer from 1-5"""
start_time = time.time()
stopwatch=0 # initializing
while stopwatch <= 5:
current_time = time.time()
stopwatch = current_time - start_time
entry_field.delete(0, END)
entry_field.insert(0, str(format(stopwatch, ".1f")) " sec")
time.sleep(0.01)
entry_field = Entry(win, width=35, borderwidth=5)
entry_field.pack()
message_1 = Label(win, text='5 second stopwatch')
message_1.pack()
button_1 = Button(win, text='START', command=start_timer)
button_1.pack()
win.mainloop()
Комментарии:
1. нельзя использовать циклы в том же потоке, что и tkinter, они блокируют основной цикл, однако вы можете использовать либо
.update()
метод (не рекомендуется), либо.after()
циклы, либо другой поток
Ответ №1:
Вы не можете использовать time.sleep
tkinter, так как он блокирует графический интерфейс до его завершения. Для tkinter вы должны использовать root.after
, например , это:
def start_timer():
"""begin timer from 1-5"""
global start_time, stopwatch
start_time = time.time()
stopwatch=0 # initializing
tick_timer()
def tick_timer():
global start_time, stopwatch
if stopwatch <= 5:
current_time = time.time()
stopwatch = current_time - start_time
entry_field.delete(0, END)
entry_field.insert(0, "%.1f" % stopwatch " sec")
win.after(100, tick_timer) #Wait 100ms then run again
Это разбивает таймер на две функции. start_timer
инициализирует переменные, а затем вызывает tick_timer
. Это делает то же самое, что и раньше, но в конце я использовал win.after
вместо time.sleep
того, чтобы tick_timer
снова вызывать функцию через 100 мс. Затем это работает, как и ожидалось.