嗨,我有一个非常具体的代码问题,我需要一双新鲜的眼睛来看待。我正在尝试为我编程的奥赛罗游戏制作GUI。我刚开始制作绿色瓷砖,我将玩游戏。为了看到一切正常,我做了一个简单的功能,每次点击其中一个瓷砖时调用。然后该函数应该打印我刚刚单击控制台的磁贴的坐标。但它的作用是打印[7, 7]
。这当然是最后创建的瓷砖的坐标。无论如何我不知道我做错了什么,但我的猜测是我不完全理解.bind()
函数,谢谢你的帮助。
代码:
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 :(得分:3)
你在函数中尝试过closing x和y吗?
问题是,在循环结束时,函数查找范围中的x
和y
已经更改为7,7。解决方案是创建一个设置所需变量的新范围,并且可以使用返回函数的函数来完成。
尝试更改:
lambda event: print_cors(event, [x,y])
要:
(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
答案 1 :(得分: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
了解更多解释。