0

我可以看到我有一个与如何在函数调用中间更新 Tkinter 画布类似的问题?但我无法将接受的答案翻译成我的情况。在那个 SO 答案中,调用自身的函数的解决方案原则上很好,但我需要将一个列表传递给a函数,而不仅仅是调用它。

顺便说一句,是的,我知道该程序有效:打印a第一行的列表#'d out in def renderGUI(a):works就好了

问题:我如何让 Tkinter 将列表a(0 表示灯关闭)设置为开关?

请注意,我也尝试w.update_idletasks()过,尽管有些人似乎对这种方法很失望。

代码如下

提前谢谢了:

from sys import stdout
from Tkinter import *
from time import sleep

numLights = 30
a     = [0,0,0,0,0,0,5,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]
speed = [0,0,0,0,0,0,5,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]

# now set the speeds
for i in range (0,numLights):
    #print "i: " + str(i)
    if a[i] > 0:
        speed[i] = a[i]

# speed[n] is the speed that the nth light will travel at.  the bigger the number the slower: its the number of passes it dwells on each light

master = Tk()
w = Canvas(master, width=1000, height=100)
master.title("Speedlights")
w.pack()

size = 8
space = 12
offsetL = 10
offsetD = 35

for i in range (1,numLights):
    w.create_oval((i*space)+offsetL,offsetD,(i*space)+size+offsetL,offsetD+size)

def renderGUI(a):
    #print a
    for k in range (0,numLights):
        if a[k]>0:
            #then it must be 'on' #tg='L'+str(i)
            w.create_oval((k*space)+offsetL,offsetD,(k*space)+size+offsetL,offsetD+size, fill="red")#, tags=(tg))
        else:
            #turn it off
            w.create_oval((k*space)+offsetL,offsetD,(k*space)+size+offsetL,offsetD+size, fill="grey")#, tags=(tg))

# set this up as a function?
for i in range (0,numLights):
    master.after(100, renderGUI(a))
    w.update_idletasks()    
    for n in range(0,numLights):
        if a[n]>1:
            a[n] = a[n]-1
        elif a[n] == 1:
                #then its about to become nought, right?
                a[n-1] = speed[n]
                speed[n-1] = speed[n]
                a[n] = a[n]-1
                continue
        continue

btn = Button(master, text='Stop', width=20, command=master.destroy)
btn.pack()
master.mainloop()
4

1 回答 1

0

为了使您的程序正常工作,只需将您的for循环放在一个函数中并通过以下方式调用它after

def f():
    for i in range (0,numLights):
        master.after(100, renderGUI(a))
        w.update_idletasks()    
        for n in range(0,numLights):
            if a[n]>1:
                a[n] = a[n]-1
            elif a[n] == 1:
                    #then its about to become nought, right?
                    a[n-1] = speed[n]
                    speed[n-1] = speed[n]
                    a[n] = a[n]-1
                    continue
            continue

btn = Button(master, text='Stop', width=20, command=master.destroy)
btn.pack()
master.after(1, f)
master.mainloop()

但是,如果你想摆脱update_idletasks,你可以使用协程(在这里包装到装饰器中):

def updatesdisplay(root, t=0):
    def _updatesdisplay(func):
        def driver(iterator):
            try: next(iterator)
            except StopIteration: pass
            else: 
                if t: root.after(t, driver, iterator)
                else: root.after_idle(driver, iterator)
        def wrapped():
            driver(func())
        return wrapped
    return _updatesdisplay

@updatesdisplay(master, 100) # 100 because we want to slow things down a bit
def f():
    for i in range (0,numLights):
        renderGUI(a)
        yield # window gets updated here
        for n in range(0,numLights):
            if a[n]>1:
                a[n] = a[n]-1
            elif a[n] == 1:
                    #then its about to become nought, right?
                    a[n-1] = speed[n]
                    speed[n-1] = speed[n]
                    a[n] = a[n]-1
                    continue
            continue

btn = Button(master, text='Stop', width=20, command=master.destroy)
btn.pack()
master.after(1, f)
master.mainloop()
于 2013-10-04T11:40:52.793 回答