tkinter:如何在同一处理程序中的小部件更改之间插入延迟?
tkinter: how do I insert a delay between widget changes within the same handler?
大约两年前,当我试图在 Tkinter 上模拟 LED 时,我问过一个类似的问题 canvas。解决方案是使用 canvas after() 方法而不是 sleep() 函数来引入小部件更新之间的延迟。
从那时起,我发现了tk_tools模块,它具有内置功能来创建LED,太棒了!但是我现在遇到了和以前一样的问题,就是:如何在每个LED的开启(变为绿色)之间有1秒的延迟?
当 运行 下面的代码实际发生的是 LED 显示为关闭状态(灰色),然后当我单击 'Start' 按钮时,有 4 秒的延迟所有 LED 同时亮起。
谢谢。
约翰尼姆
# LED array simulation
from tkinter import *
import tk_tools as tkt
from time import *
# turn on LEDs (change to green) with a 1-second delay between each
def turn_on():
for led in range(4):
led_array[led].to_green()
sleep(1)
# list to hold a 4-LED array
led_array = []
# GUI
root = Tk()
# create 4 LED widgets, store them in led_array[], display them
for i in range(4):
led_array.append(tkt.Led(root, size=30))
led_array[i].grid(row=0, column=i)
# create button to initiate LED turn-on sequence
start = Button(root, text='Start', padx=20, command=turn_on)
start.grid(row=1, columnspan=4)
root.mainloop()
我想每当回调函数完成执行时,所有 LED 都会同时发光。所以我决定创建一个 thread 并使用 after()
来停止时间(sleep()
停止主线程,使其持续 4 秒)
# LED array simulation
from tkinter import *
import tk_tools as tkt
from time import *
import threading
import sys
class Testing(Tk):
def __init__(self):
super().__init__()
self.led_array = []
for i in range(4):
self.led_array.append(tkt.Led(self, size=30))
self.led_array[i].grid(row=0, column=i+1)
self.start = Button(self, text='Start', padx=20, command=self.zawardu)
self.start.grid(row=1, columnspan=4)
def zawardu(self):
a=threading.Thread(target=self.turn_on)
a.start()
def turn_on(self):
self.start.config(state=DISABLED) # to stop creating another thread unnec..
for led in range(len(self.led_array)):
self.led_array[led].to_green()
self.after(1000) # stops time
self.start.config(state=NORMAL)
sys.exit(0) # ensures after exec. thread is killed
# class format to use after() and threading to reset the button status
Testing().mainloop()
最好避免停止应用程序的睡眠并使用 after
。要么将调用链接到后回调,以便每个调用下一个调用,要么在循环中为每个 led 调用它们,但在 1、2、3 和 4 秒延迟。
链接版本:
# LED array simulation
from tkinter import *
import tk_tools as tkt
# list to hold a 4-LED array
led_array = []
# GUI
root = Tk()
# create 4 LED widgets, store them in led_array[], display them
for i in range(4):
led_array.append(tkt.Led(root, size=30))
led_array[i].grid(row=0, column=i)
# Both answers are common to here.
def on_after( led_list ):
led_list[0].to_green() # Set first item in the list.
if len( led_list ) > 1:
# Call on_after again with a shortened list.
root.after( 1000, on_after, led_list[1:] )
else:
# Enable the start button
start.config( state = NORMAL )
# turn on LEDs (change to green) with a 1-second delay between each
def turn_on():
start.config( state = DISABLED ) # Disable the button
root.after( 1000, on_after, led_array)
# create button to initiate LED turn-on sequence
start = Button(root, text='Start', padx=20, command=turn_on)
start.grid(row=1, columnspan=4)
root.mainloop()
循环版:
# Both answers are common to here.
def on_after( led ):
led.to_green()
def enable():
start.config( state = NORMAL )
# turn on LEDs (change to green) with a 1-second delay between each
def turn_on():
start.config( state = DISABLED ) # Disable the button
for ix, led in enumerate( led_array ):
# Call on_after 4 times with 1 to 4 second delays
root.after( 1000 * (1+ix), on_after, led )
root.after( 1000*(ix+1), enable )
# create button to initiate LED turn-on sequence
start = Button(root, text='Start', padx=20, command=turn_on)
start.grid(row=1, columnspan=4)
root.mainloop()
我可能会使用链接版本,尽管在这种情况下循环版本可能更容易理解。
大约两年前,当我试图在 Tkinter 上模拟 LED 时,我问过一个类似的问题 canvas。解决方案是使用 canvas after() 方法而不是 sleep() 函数来引入小部件更新之间的延迟。
从那时起,我发现了tk_tools模块,它具有内置功能来创建LED,太棒了!但是我现在遇到了和以前一样的问题,就是:如何在每个LED的开启(变为绿色)之间有1秒的延迟?
当 运行 下面的代码实际发生的是 LED 显示为关闭状态(灰色),然后当我单击 'Start' 按钮时,有 4 秒的延迟所有 LED 同时亮起。
谢谢。 约翰尼姆
# LED array simulation
from tkinter import *
import tk_tools as tkt
from time import *
# turn on LEDs (change to green) with a 1-second delay between each
def turn_on():
for led in range(4):
led_array[led].to_green()
sleep(1)
# list to hold a 4-LED array
led_array = []
# GUI
root = Tk()
# create 4 LED widgets, store them in led_array[], display them
for i in range(4):
led_array.append(tkt.Led(root, size=30))
led_array[i].grid(row=0, column=i)
# create button to initiate LED turn-on sequence
start = Button(root, text='Start', padx=20, command=turn_on)
start.grid(row=1, columnspan=4)
root.mainloop()
我想每当回调函数完成执行时,所有 LED 都会同时发光。所以我决定创建一个 thread 并使用 after()
来停止时间(sleep()
停止主线程,使其持续 4 秒)
# LED array simulation
from tkinter import *
import tk_tools as tkt
from time import *
import threading
import sys
class Testing(Tk):
def __init__(self):
super().__init__()
self.led_array = []
for i in range(4):
self.led_array.append(tkt.Led(self, size=30))
self.led_array[i].grid(row=0, column=i+1)
self.start = Button(self, text='Start', padx=20, command=self.zawardu)
self.start.grid(row=1, columnspan=4)
def zawardu(self):
a=threading.Thread(target=self.turn_on)
a.start()
def turn_on(self):
self.start.config(state=DISABLED) # to stop creating another thread unnec..
for led in range(len(self.led_array)):
self.led_array[led].to_green()
self.after(1000) # stops time
self.start.config(state=NORMAL)
sys.exit(0) # ensures after exec. thread is killed
# class format to use after() and threading to reset the button status
Testing().mainloop()
最好避免停止应用程序的睡眠并使用 after
。要么将调用链接到后回调,以便每个调用下一个调用,要么在循环中为每个 led 调用它们,但在 1、2、3 和 4 秒延迟。
链接版本:
# LED array simulation
from tkinter import *
import tk_tools as tkt
# list to hold a 4-LED array
led_array = []
# GUI
root = Tk()
# create 4 LED widgets, store them in led_array[], display them
for i in range(4):
led_array.append(tkt.Led(root, size=30))
led_array[i].grid(row=0, column=i)
# Both answers are common to here.
def on_after( led_list ):
led_list[0].to_green() # Set first item in the list.
if len( led_list ) > 1:
# Call on_after again with a shortened list.
root.after( 1000, on_after, led_list[1:] )
else:
# Enable the start button
start.config( state = NORMAL )
# turn on LEDs (change to green) with a 1-second delay between each
def turn_on():
start.config( state = DISABLED ) # Disable the button
root.after( 1000, on_after, led_array)
# create button to initiate LED turn-on sequence
start = Button(root, text='Start', padx=20, command=turn_on)
start.grid(row=1, columnspan=4)
root.mainloop()
循环版:
# Both answers are common to here.
def on_after( led ):
led.to_green()
def enable():
start.config( state = NORMAL )
# turn on LEDs (change to green) with a 1-second delay between each
def turn_on():
start.config( state = DISABLED ) # Disable the button
for ix, led in enumerate( led_array ):
# Call on_after 4 times with 1 to 4 second delays
root.after( 1000 * (1+ix), on_after, led )
root.after( 1000*(ix+1), enable )
# create button to initiate LED turn-on sequence
start = Button(root, text='Start', padx=20, command=turn_on)
start.grid(row=1, columnspan=4)
root.mainloop()
我可能会使用链接版本,尽管在这种情况下循环版本可能更容易理解。