我正在制作一个简单的程序,该程序创建tkinter.Button()
的3x3矩阵,当按下按钮时,它应该在上面显示“ Clicked”文本。
但是结果似乎是位于同一列上的按钮被绑定到同一命令-以该列最后一行的按钮为目标的命令。
from tkinter import *
root = Tk()
text = [[None]*3]*3
buttons = [[None]*3]*3
def action(i, j):
text[i][j].set('Clicked')
for i in range(3):
for j in range(3):
text[i][j] = StringVar()
text[i][j].set('(%d, %d)' % (i,j))
buttons[i][j] = Button(root, command = lambda i=i, j=j : action(i, j))
buttons[i][j].config(textvariable = text[i][j], width = 9, height = 5)
buttons[i][j].grid(row = i, column = j)
root.mainloop()
答案 0 :(得分:2)
问题不在于命令,而在于创建列表的方式。
当您将一个列表相乘时,实际上是对该单个列表的引用也相乘(请参见this question)。运行以下代码时,您会看到此信息:
text = [[None]*3]*3
print([id(x) for x in text])
因此,当您更改其中一个列表中的项目时,该项目在所有列表中都会更改。因此,您的列表看起来不像[[1,2,3],[4,5,6],[7,8,9]]
,而是像[[7,8,9],[7,8,9],[7,8,9]]
。然后,当您认为设置了StringVar数字1时,实际上是设置了Stringvar数字7,因此更改了按钮数字7。
您可以使用列表理解而不是乘法来创建三个单独的列表。如下面的代码所示,这将产生三个单独的列表。
text = [[None]*3 for _ in range(3)]
print([id(x) for x in text])