Ткинтер неожиданное поведение - PullRequest
2 голосов
/ 19 октября 2010

Я писал длинный графический интерфейс на Python, используя Tkinter. Одна вещь, которую я не понимаю, это то, почему я не могу связать события с виджетами в цикле. В приведенном ниже коде привязка работает хорошо, если я делаю это вручную (закомментированный код), но не в цикле for. Я что-то не так делаю?

импорт Ткинтер

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 ]

3 голосов
/ 19 октября 2010

Вы можете решить проблему с помощью:

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.

3 голосов
/ 19 октября 2010

Ваши затворы (лямбды) не работают так, как вы ожидаете. Они сохраняют ссылки на i, который мутирует во время итерации цикла, и в конце все лямбды из одного и того же цикла ссылаются на одну и ту же последнюю кнопку.

Вот иллюстрация поведения:

>>> k = []
>>> for i in range(5):
...     k.append(lambda: i)
>>> k[0]()
4
>>> [f() for f in k]
[4, 4, 4, 4, 4]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...