gpt4 book ai didi

Python3 tkinter : Deletion of row of widgets works on first iteration but not on subsequent iterations

转载 作者:太空宇宙 更新时间:2023-11-04 02:54:20 25 4
gpt4 key购买 nike

我使用 tkinter 条目小部件创建了一个由行和列组成的小部件。我希望在每一行旁边放置一个“-”按钮,这将简单地删除该行。

我的对象叫做 DisplayTable,它是 tk.Frame 的一个实例,它由多行条目组成,每行包含一个带有 的按钮>- 应该可以轻松删除该行。

我将尝试跳过代码中较为冗长的部分,以便切入正题。 DisplayTable 对象在 __init__ 中创建行列表 self.rows。随着行的添加,此列表将增长。例如,一个包含三行和两列的表格如下所示:

[
[<tkinter.Entry object>, <tkinter.Entry object>, <tkinter.Button object>],
[<tkinter.Entry object>, <tkinter.Entry object>, <tkinter.Button object>],
[<tkinter.Entry object>, <tkinter.Entry object>, <tkinter.Button object>]
]

生成的图形: Resulting graphic

DisplayTable.add_row() 中,我有这个代码片段(删除了很​​多额外的代码以达到目的):

def add_row(self):
row = []
for i in range(self.columns):
cell = tk.Entry(self)
cell.grid(row=offset, column=i)
row.append(cell)

row_to_delete = len(self.rows)
btn = tk.Button(self, image=self.minus, command=lambda: self.delete_row(row_to_delete))
btn.grid(row=offset, column=self.columns)
row.append(btn)

self.rows.append(row)

上面的代码片段非常适合将行添加到数组的末尾。它适用于一次删除行。

def delete_row(self, row_number):
for widget in self.rows[row_number]:
widget.destroy()
self.rows.pop(row_number)

# re-assign the delete row buttons
for i, row in enumerate(self.rows):
button = row[-1]
button.configure(command=lambda: self.delete_row(i))

我在 delete_row 中的意图是重新分配删除按钮,因为 self.rows 的行索引刚刚针对每一行更改。执行此函数后,我得到的行为是始终删除最后一个 row_number。例如,如果有 10 行,则始终删除索引为 9 的行。

用更直接的引用替换删除按钮的重新分配似乎不会改变行为:

def delete_row(self, row_number):
for widget in self.rows[row_number]:
widget.destroy()
self.rows.pop(row_number)

# re-assign the delete row buttons
for i, row in enumerate(self.rows):
self.rows[i][-1].configure(command=lambda: self.delete_row(i))

使用 print 命令,我已经验证变量 i 在每一轮中肯定是不同的,并且引用的 button 对象是不同的按钮,因此分配的 command 也应该不同。不知何故,似乎只有最后一次循环才坚持使用所有按钮,而不仅仅是它打算使用的按钮。

最佳答案

for i, row in enumerate(self.rows):
button = row[-1]
button.configure(command=lambda: self.delete_row(i))

单击该按钮时,您将删除由变量i 的值指定的行在那一刻。由于此循环在您可能单击按钮之前早就完成了,因此 i 将始终引用最后一行。这是lambdas在循环中的一个常见问题,解决方案是捕获默认参数中所有使用的变量的值:command=lambda i=i: self.delete_row(i))

我认为更好的方法是将您的 row 变量而不是索引传递给 delete_row() - 这样,删除行时无需更改任何内容。您可以迭代 for widget in row: 以删除小部件,并通过 self.rows.remove(row) 删除行本身。

关于Python3 tkinter : Deletion of row of widgets works on first iteration but not on subsequent iterations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42905290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com