Создание поведения, которое должно выполняться в течение определенного периода времени, является частой проблемой; Вы можете заняться этим с выделенным классом Waiter
; это позволяет избежать использования потоков, которые плохо поддерживаются tkinter
.
В следующем примере открывается окно с меткой и кнопкой. При нажатии кнопки метка будет обновляться каждые 10 секунд, а затем останавливаться.
Повторное нажатие кнопки в течение 10 секунд не имеет никакого эффекта; после этого он перезапускает процесс еще на 10 секунд.
import Tkinter as tk # tkinter if python >= 3
import time
import random
class Waiter(object):
def __init__(self, waiting_time):
"""
:param waiting_time: int, in seconds
"""
self.waiting_time = waiting_time
self.expiring_time = time.time() + self.waiting_time
self.waiting = True
# print('waiter started')
def stop(self):
# print('waiter stopping')
self.expiring_time = None
self.waiting = False
def is_waiting(self):
"""returns True while waiting, false otherwise"""
if time.time() > self.expiring_time:
self.stop()
return self.waiting
def atest():
global waiter
if waiter is None:
waiter = Waiter(10)
_atest()
def _atest():
""" equivalent to:
while the waiter is waiting,
change the label every second),
then destroy the waiter
"""
global waiter
if waiter.is_waiting():
a.set(random.random())
# print(time.time())
t.after(1000, _atest)
else:
waiter = None
if __name__ == '__main__':
waiter = None
t = tk.Tk()
a = tk.StringVar()
a.set('0')
tk.Label(t, textvariable=a).pack()
tk.Button(t, text='test', command=atest).pack()
t.mainloop()
Примечание:
Вы могли бы сделать _atest
внутренней функцией atest
, но, возможно, ее легче понять, как есть?
использование import Tkinter as tk
вместо from Tkinter import *
предотвращает загромождение пространства имен и, возможно, делает код более понятным.
Возможно, вам следует рассмотреть возможность использования Python 3.