- Button 的 command,然后command 指向一个具体的函数,可以通过lambda 传参,
- bind 函数,可以绑定单击、双击多种操作,但是传参需要用到额外的库 functools
def createGameURLs(self):
self.button = []
for i in range(3):
self.button.append(Button(self, text='Game '+str(i+1),command=lambda:self.open_this(i)))
self.button[i].grid(column=4, row=i+1, sticky=W)
def open_this(self, myNum):
print(myNum)
这里面虽然调用了匿名函数,但是没有声明参数 i , 参数传递之后都是i 循环到末尾的值,传参失败。热心网友给出解决办法:将lambda改为lambda i = i:self.open_this(i).
这可能看起来很神奇,但这就是正在发生的事情。当您使用该lambda定义函数时,open_this调用在您定义函数时不会获取变量 i 的值,相反,它会产生一个闭包,这有点像对自己的说法,“我应该在我被调用时,寻找变量 i 的值。”当然,在循环结束后调用该函数,所以此时我将始终等于循环中的最后一个值,使用 i = i 会导致函数在定义lambda时存储 i 的当前值,而不是等待稍后查找i的值.
看起来可能有点绕,大致意思应该是 command 指向一个 匿名函数,这个匿名函数的参数是i, 而这个i 被赋值给 for 循环里的变量i, 函数体是 self.AddNumber(i),如果写成如下格式可能更好理解一些:
def createGameURLs(self):
self.button = []
for i in range(3):
self.button.append(Button(self, text='Game '+str(i+1),command=lambda x=i:self.open_this(x)))
self.button[i].grid(column=4, row=i+1, sticky=W)
def open_this(self, myNum):
print(myNum)
附第 2 种写法的尝试:
from functools import partial
def createGameURLs(self):
self.button = []
for i in range(3):
self.button.append(Button(self, text='Game '+str(i+1)))
self.button[i].bind('<Button-1>', partial(self.open_this, i))
self.button[i].grid(column=4, row=i+1, sticky=W)
def open_this(self, myNum, event):
print(myNum)
需要注意的是,这种写法需要在 具体调用 的函数里添加一个额外的参数 event
参考资料: