2013-02-24 270 views
1

我在使用Tkinter after()方法時遇到問題。 實際上,我想要做的是儘快改變一些輸入框的背景顏色。讓我們這一段代碼(這是我工作的劇本不同,但所描述的情況是一樣的):Python:使用Tkinter動態更改輸入顏色

import Tkinter as tk 

root = tk.Tk() 
root.option_add("*Entry.Font","Arial 32 bold") 

emptyLabel=tk.Label() 
emptyLabel.grid(row=4) #Empty label for geometry purpose 
entryList=[] 

for x in range(4): 
    entryList.append([]) 
    for y in range(4): 
     entryList[x].append('') 
     entryList[x][y]=tk.Entry(root, bg="white",width=2,justify="center", 
           takefocus=True,insertofftime=True) 
     entryList[x][y].grid(row=x,column=y) 

solvebt=tk.Button(root,text='Solve').grid(row=5,column=2) 
newgamebt=tk.Button(root,text='New').grid(row=5,column=1) 

#BROKEN PART STARTS HERE 

def changebg(x,y): 
    entryList[x][y]['bg']='yellow' 

for x in range(4): 
    for y in range(4): 
     entryList[x][y].after(300,changebg(x,y)) 
     #Same result with root.after(300,changebg(x,y)) 


root.mainloop() 

的問題是,當我啓動程序,我就指望它讓我看看它的「油漆」,一次一個,所有的輸入框都是黃色的。相反,會發生什麼情況,程序會凍結(300 * 16)毫秒,然後,所有突發的,每個輸入框都是黃色的!

回答

1

的問題是在這裏:

def changebg(x,y): 
    entryList[x][y]['bg']='yellow' 

for x in range(4): 
    for y in range(4): 
     entryList[x][y].after(300,changebg(x,y)) 
     #Same result with root.after(300,changebg(x,y)) 

你打電話changebg立即在雙for循環 - 你則返回值(None)傳遞給root.after。這不會導致你描述的延遲。也許你的實際代碼如下:

for x in range(4): 
    for y in range(4): 
     entryList[x][y].after(300,lambda x=x,y=y : changebg(x,y)) 

這將導致你實際描述的行爲。最終,你需要的是扁平你的小工具列表,然後通過一個一次 - 註冊下一個,如果它存在:

import itertools 
all_entries = itertools.chain.from_iterable(entryList) 
def changebg(ientries): 
    ientries = iter(ientries) #allow passing a list in as well ... 
    entry = next(ientries,None) 
    if entry is not None: 
     entry['bg'] = 'yellow' #change the color of this widget 
     root.after(300,lambda : changebg(ientries)) #wait 300ms and change color of next one. 

changebg(all_entries)