Tkinter:画布绑定到事件

Tkinter: Canvases Binded to Events

您好,我有一个非常具体的代码问题,我需要一双新的眼睛来审视。我正在尝试为我编写的 Othello 游戏制作 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()

您在函数中尝试过 closing x 和 y 吗?

问题是函数查找范围内的 xy 在循环结束时已经更改为 7, 7。解决方案是在设置所需变量的地方创建一个新范围,并且可以使用 returns 一个函数的函数来完成。

尝试更改:

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

通常的解决方案是替换:

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

更多解释。