Tkinter Frame子类MultiInput多实例按钮触发异常问题求助
嘿,这个问题的根源很明显——你把subs、adders和index定义成了类属性,而不是实例属性!这意味着所有MultiInput实例都会共享这几个变量,所以不管你操作哪个实例的按钮,都会影响到所有实例的状态。
在Python中,如果你在类定义里直接写subs = [],这个列表是属于整个类的,所有实例都会共用同一个列表。同样,index = 0也是类级别的变量,所有实例共享同一个值。这就导致点击任意一个实例的+/x按钮时,所有实例都会执行相同的展开/收起逻辑,因为它们都在操作同一个subs列表。
要解决这个问题,你只需要把这些类属性改成实例属性,也就是在__init__方法里初始化它们,每个实例拥有自己独立的subs、adders和index。具体修改如下:
修改后的完整代码
from tkinter import Frame, Button, IntVar, Radiobutton, Label, Tk class MultiInput(Frame): """use .add(Widged)-Method to add widged!""" def __init__(self, parent): Frame.__init__(self, parent) # 将类属性改为实例属性,每个实例独立拥有 self.subs = [] self.adders = [] self.index = 0 self.indexVar = IntVar() self.indexVar.set(0) self.dropdown = Button(self, text="+", command=self.drop) self.dropdown.grid(row=0, column=0) self.dropup = Button(self, text="x", command=self.undrop) # 初始化时隐藏收起按钮,保持初始界面整洁 self.dropup.grid_forget() def drop(self): num = -1 self.dropdown.grid_forget() self.dropup.grid(row=0, column=0) for i in range(len(self.subs)): num += 1 if i != self.index: self.subs[i].grid(column=1, row=num+1) self.adders[i].grid(column=0, row=num+1) def undrop(self): for i in range(len(self.subs)): self.subs[i].grid_forget() self.adders[i].grid_forget() self.subs[self.index].grid(row=0, column=1) self.dropup.grid_forget() self.dropdown.grid(row=0, column=0) def add(self, Widged): if len(self.subs) == 0: self.subs.append(Widged) self.adders.append(Radiobutton(self, variable=self.indexVar, command=self.change, value=0)) self.change() else: self.subs.append(Widged) self.adders.append(Radiobutton(self, variable=self.indexVar, command=self.change, value=len(self.subs)-1)) def change(self): self.index = self.indexVar.get() self.undrop()
关键修改点说明
- 将类属性移到
__init__中:
原来的subs = []、adders = []、index = 0是类属性,现在改成在__init__里初始化self.subs = []、self.adders = []、self.index = 0,这样每个MultiInput实例都有自己独立的列表和索引变量,互不干扰。 - 初始化时隐藏收起按钮:
原来的代码里self.dropup没有初始隐藏,导致实例创建后会同时显示+和x按钮,现在在__init__里加上self.dropup.grid_forget(),让初始状态只显示+按钮,符合预期交互逻辑。 - 确保所有方法都引用实例属性:
所有方法里的subs、adders、index都改成self.subs、self.adders、self.index,确保操作的是当前实例自己的变量,不会影响其他实例。
验证调用示例
你的调用代码不需要修改,直接运行就可以看到每个MultiInput实例独立工作了:
root = Tk() multi = MultiInput(root) multi.add(Label(multi, text="Label 1")) multi.add(Label(multi, text="Label 2")) multi.add(Label(multi, text="Label 3")) multi.pack() multi2 = MultiInput(root) multi2.add(Label(multi2, text="Label 4")) multi2.add(Label(multi2, text="Label 5")) multi2.add(Label(multi2, text="Label 6")) multi2.pack() multi3 = MultiInput(root) multi3.add(Label(multi3, text="Label 7")) multi3.add(Label(multi3, text="Label 8")) multi3.add(Label(multi3, text="Label 9")) multi3.pack() root.mainloop()
现在点击任意一个实例的+按钮,只有该实例会展开单选列表;切换单选按钮也只会改变当前实例显示的Widget,其他实例完全不受影响。
内容的提问来源于stack exchange,提问作者phseiff
相关产品推荐
相关产品推荐

