0

I asked a similar question about two years ago when I was trying to emulate LEDs on a Tkinter canvas. The solution then was to use the canvas after() method instead of the sleep() function to introduce a delay between widget updates.

Since then, I have discovered the tk_tools module which has a buit-in function to create LEDs, great! But I now have the same issue as before, which is: How to have a 1-second delay between the turning on (change to green) of each LED?

What actually happens when running the code below is that the LEDs are displayed in their OFF state (gray), then when I click the 'Start' button, there's a 4-second delay after which all LEDs turn on simultaneously.

Thank you. Johnnym

# 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()
4

2 回答 2

0

我猜每当回调函数完成执行时,所有 LED 都会同时发光。所以我决定创建一个线程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()
于 2020-10-25T10:19:29.097 回答
0

最好避免停止应用程序并使用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()

我可能会使用链接版本,尽管在这种情况下循环版本可能更容易理解。

于 2020-10-25T18:15:36.973 回答