2010-10-18 56 views
2

我一直在使用Tkinter在Python中編寫一個很長的GUI。我不明白的一件事是爲什麼我無法將事件綁定到循環中的小部件。在下面的代碼中,如果我手動執行(註釋掉代碼),而不是在for循環中,則綁定工作正常。難道我做錯了什麼?Tkinter意外的行爲

進口的Tkinter

root = Tkinter.Tk() 

b1 = Tkinter.Button(root, text="Button 1") 
b1.pack() 
b1.focus_set() 
b2 = Tkinter.Button(root, text="Button 2") 
b2.pack() 
b3 = Tkinter.Button(root, text="Button 3") 
b3.pack() 


def up_and_down(*buttons): 

    for i in range(len(buttons)-1): 
    buttons[i].bind("<Down>", lambda x: buttons[i+1].focus_set()) 

    for i in range(1, len(buttons)): 
    buttons[i].bind("<Down>", lambda x: buttons[i-1].focus_set()) 

    ''' 
    buttons[0].bind("<Down>", lambda x: buttons[1].focus_set()) 
    buttons[1].bind("<Down>", lambda x: buttons[2].focus_set()) 

    buttons[1].bind("<Up>", lambda x: buttons[0].focus_set()) 
    buttons[2].bind("<Up>", lambda x: buttons[1].focus_set()) 
    ''' 

up_and_down(b1, b2, b3) 

root.mainloop() 
+0

這將是很好的,如果你可以添加正在生成的錯誤。 – pyfunc 2010-10-18 21:57:34

+0

它可能與你在循環中不使用「」「這一事實有關嗎? – nmichaels 2010-10-18 22:04:30

+0

@pyfunc當我按下向下箭頭例如,我得到這個錯誤。異常在Tkinter回調 回溯(最近呼叫最後): 文件「/usr/lib/python2.6/lib-tk/Tkinter.py」,行1413,在__call__中 返回self.func(* args) 文件「events.py」,第17行,在 按鈕[i] .bind(「」,lambda x:buttons [i + 1] .focus_set()) IndexError:元組索引超出範圍 – Thea 2010-10-20 11:58:07

回答

3

你關閉(lambda表達式),你希望他們不工作。它們繼續引用i,它在循環迭代時發生變化,最後,來自同一循環的所有lambda表示引用同一個最後一個按鈕。

這裏是行爲的說明:

for i in range(len(buttons)-1): 
    buttons[i].bind("<Down>", lambda x, i=i: buttons[i+1].focus_set()) 

for i in range(1, len(buttons)): 
    buttons[i].bind("<Down>", lambda x, i=i: buttons[i-1].focus_set()) 

注意i=i參數傳遞給lambda關閉:

>>> k = [] 
>>> for i in range(5): 
...  k.append(lambda: i) 
>>> k[0]() 
4 
>>> [f() for f in k] 
[4, 4, 4, 4, 4] 
+0

不錯的插圖 – 2010-10-19 12:55:57

+0

嗯....我明白了。我需要一些時間來更好地學習lambda。謝謝你的幫助。 – Thea 2010-10-20 11:49:22

+0

這不是關於lambdas,而是關於關閉。你可以用'def'來定義一個函數,而不是循環中的lambda,結果是一樣的。 – 2010-10-21 06:43:52

3

你可以解決這個問題。

+0

非常感謝!這解決了問題! – Thea 2010-10-20 11:49:44