2015-09-12 2 views
0

Привет, У меня есть очень специфическая проблема с кодом. Мне понадобятся свежая пара глаз. Я пытаюсь создать графический интерфейс для игры Othello, которую я запрограммировал. Я только что начал и сделал зеленые плитки, в которых я буду играть. Чтобы увидеть, что все работает, я сделал простую функцию, которая вызывается каждый раз, когда клик по одному из фрагментов. Затем функция должна распечатать координаты плитки, которую я только что нажал на консоль. Однако он делает то, что он печатает [7, 7]. Это, конечно, координаты самой последней плитки. Во всяком случае, я не знаю, что я делаю неправильно, но я предполагаю, что я не совсем понимаю функцию .bind(), спасибо за любую помощь.Tkinter: Холсты, привязанные к событиям

Код:

from tkinter import * 

def print_cors(event, cors): 
    print(cors) 


class GridFrame: 
    def __init__(self, master): 
     board = Frame(master, height=500, width=800, bg="brown") 
     board.grid() 
     self.column_frame_list = [None]*8 
     for x in range(0, len(self.column_frame_list)): 
      self.column_frame_list[x] = [None]*8 
      for y in range(0, len(self.column_frame_list[x])): 
       self.column_frame_list[x][y] = Canvas(board, height=55, width=55, bg="green", bd=0, highlightthickness=0, relief='ridge') 
       self.column_frame_list[x][y].bind("<Button-1>", lambda event: print_cors(event, [x,y])) 
       self.column_frame_list[x][y].grid(row=y, column=x) 

root = Tk() 
root.wm_title("Reversi") 
grid_frame = GridFrame(root) 
root.mainloop() 
+0

http://stackoverflow.com/questions/17677649/tkinter-assign-button-command-in-loop-with-lambda –

ответ

3

Вы пробовали closing х и у в функции?

Проблема в том, что x и y в объеме, в котором функции смотрят, уже к 7, 7 к концу цикла уже изменены. Решение состоит в том, чтобы создать новую область, в которой заданы нужные переменные, и это можно сделать с помощью функции, которая возвращает функцию.

Попробуйте изменить:

lambda event: print_cors(event, [x,y]) 

To:

(lambda _x, _y: lambda event: print_cors(event, [_x,_y]))(x,y) 

Это реконструкция вашей проблемы:

>>> l = [] 
>>> for lam in l: 
...  print lam() 
... 
>>> l = [] 
>>> for x in range(3): 
...  l.append(lambda : x) 
... 
>>> for lam in l: 
...  print lam() 
... 
2 
2 
2 

И это решение с боксом переменные петли внутрь (закрытие), добавив их в качестве параметров внешней функции:

>>> l = [] 
>>> for x in range(3): 
...  l.append((lambda _x: lambda : _x)(x)) # close x into the function 
... 
>>> for lam in l: 
...  print lam() 
... 
0 
1 
2 
+0

Спасибо, что решила его, но не могли бы вы объяснить, что это на самом деле делает или может быть прямо меня к источнику, который может мне сказать? –

+0

Это в основном создание среды с функцией: https://en.wikipedia.org/wiki/Closure_%28computer_programming%29 –

+0

Хорошо, спасибо вам большое! –

1

Обычное решение состоит в замене:

self.column_frame_list[x][y].bind("<Button-1>", lambda event: print_cors(event, [x,y])) 

с:

self.column_frame_list[x][y].bind("<Button-1>", lambda event, x=x, y=y: print_cors(event, [x,y])) 

См Tkinter assign button command in loop with lambda

для более объяснений.