Tkinter出乎意料的行为

时间:2010-10-18 21:36:23

标签: python events user-interface loops tkinter

我一直在使用Tkinter在Python中编写一个很长的GUI。我不明白的一件事是为什么我不能将事件绑定到循环中的小部件。在下面的代码中,如果我手动(注释掉代码)但在for循环中没有绑定,则绑定很有效。我做错了吗?

导入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()

2 个答案:

答案 0 :(得分:3)

你的闭包(lambdas)没有像你期望的那样工作。它们保留对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]

答案 1 :(得分:3)

您可以使用以下方法解决问题:

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参数。