我想在函数中传递2个变量参数,以将其分配给Button
command
。这些变量会在for
循环内更改,该循环还会创建按钮。
主要受一些here和here的最高启发所启发,这是我根据阅读内容尝试解决此问题的失败尝试:
我尝试使用partial
:
self.dct[(i, j)] = Button(command=partial(self.on_click, i, j))
另一种尝试:
self.dct[(i, j)] = Button(command=partial(partial(self.on_click, i), j))
另一个:
self.dct[(i, j)] = Button(command=partial(self.on_click, [i, j]))
..你猜怎么着?
tup = [i, j]
self.dct[(i, j)] = Button(command=partial(self.on_click, tup))
然后,lambda
:
self.dct[(i, j)] = Button(command=lambda i=i, j=j: self.on_click(i, j))
这是我的代码:
import tkinter as tk
from functools import partial
class Board(tk.Frame):
board = None
images = None
tile = None
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.tile = {}
for i in range(10):
for j in range(10):
self.tile[(i, j)]['btn_obj'] = tk.Button(self.board, command=partial(partial(self.on_click, i), j))
def on_click(self, i, j):
print("X: {}, Y:{}".format(j, i))
partial
总是会导致如下错误:
TypeError: on_click() takes 2 positional arguments but 3 were given
参数数量总是不匹配。
与此同时,lambda
获得了错误的变量值,从而导致tkinter
方面出现了一些错误。
答案 0 :(得分:2)
您问题中的lambda应该起作用:
<p>Example Situation</p>
<table>
<tr>
<td>
<p id="question1">Question 1</p>
<input type="radio" name="question1" id="yes1" value="yes">
<label for="yes1">Yes</label>
<input type="radio" name="question1" id="no1" value="no">
<label for="no1">No</label>
</td>
<td>
Answer 1
</td>
</tr>
<tr>
<td>
<p id="question2">Question 2</p>
<input type="radio" name="question2" id="yes2" value="yes">
<label for="yes2">Yes</label>
<input type="radio" name="question2" id="no2" value="no">
<label for="no2">No</label>
</td>
<td>
Answer 2
</td>
</tr>
</table>
这会将值tk.Button(self.board, command=lambda i=i, j=j: self.on_click(i,j))
和i
绑定为lambda参数的默认值。
我个人更喜欢lambda而不是lambda,这主要是因为我不必导入functools模块。如果您希望使用partial,它应该看起来像您的第一个示例:
j
在两种情况下,创建按钮时,都会根据tk.Button(self, command=partial(self.on_click, i, j))
和on_click
的值向i
和j
传递正确的值。
这是一个基于您的代码的示例,但是为了清楚起见,删除了一些不必要的代码:
import tkinter as tk
from functools import partial
class Board(tk.Frame):
def __init__(self, parent, method):
tk.Frame.__init__(self, parent, bd=2, relief="sunken")
for i in range(10):
for j in range(10):
if method == "lambda":
button = tk.Button(self, command=lambda i=i, j=j: self.on_click(i,j))
else:
button = tk.Button(self, command=partial(self.on_click, i, j))
button.grid(row=i, column=j)
def on_click(self, i, j):
print("X: {}, Y:{}".format(j, i))
root = tk.Tk()
board1 = Board(root, method="lambda")
board2 = Board(root, method="partial")
board1.pack(side="top", fill="both", expand=True)
board2.pack(side="top", fill="both", expand=True)
root.mainloop()