如何将tkinter Toplevel变量传入另一类的Treeview并解决报错?
这个问题我做点餐类系统时也碰到过,核心是你搞混了类和实例的区别,导致访问不到coTree这个实例属性。先给你拆解下错误根源,再给两种实操性强的修复方案:
错误原因分析
你代码里用PoS.add_custom_item(PoS,PoS.custom_item)直接通过类名调用实例方法,还把PoS类本身当作self参数传进去——但coTree是PoS类实例化后才会有的属性,类本身根本没有这个属性,自然会抛出AttributeError: type object 'PoS' has no attribute 'coTree'。
后来你试的addItem = PoS.add_custom_item(self,self.custom_item)也无效,是因为这里的self是Toplevel窗口的实例(比如你的自定义披萨窗口类的实例),不是PoS根应用的实例,方法里的self.coTree会去查找Toplevel实例的属性,当然也找不到。
修复方案一:给Toplevel传递PoS实例引用
这是最直观的方式,在打开自定义披萨窗口时,把PoS的实例传进去,让Toplevel能直接调用根应用的方法:
1. 修改PoS类中打开Toplevel的代码
假设你在PoS类里有打开自定义披萨窗口的方法,把自身实例传进去:
class PoS: def __init__(self, root): self.root = root # 初始化你的结账Treeview self.coTree = ttk.Treeview(root, columns=("Name", "Price"), show="headings") # ...其他初始化代码 def open_custom_pizza(self): # 把PoS实例self传给自定义窗口 CustomPizzaWindow(pos_instance=self)
2. 修改自定义披萨窗口类
在窗口初始化时保存PoS实例,提交时直接调用实例的add_custom_item方法:
class CustomPizzaWindow: def __init__(self, pos_instance): self.pos_instance = pos_instance # 保存根应用实例 self.win = tk.Toplevel() # ...窗口内的控件初始化(比如配料选择、价格计算等) def submit(self): # 构建自定义披萨的Item对象 name = "自定义披萨" # 替换成你实际的名称逻辑 self.total = 19.99 # 替换成你实际的总价计算逻辑 self.custom_item = Item(000, name, self.total, 'Pizza') # 调用PoS实例的方法,直接传入Item对象 self.pos_instance.add_custom_item(self.custom_item) self.win.destroy()
3. 修正PoS类的add_custom_item方法
保持它是正常的实例方法,直接使用自身的coTree属性:
class PoS: # ...其他代码 def add_custom_item(self, item): # 直接用实例的coTree插入数据 self.coTree.insert('', 'end', text='1', open=True, values=(item.name, '{:.2f}'.format(item.price)))
修复方案二:使用回调函数解耦
如果你不想让Toplevel持有整个PoS实例,可以把add_custom_item方法作为回调函数传递过去,更符合解耦设计:
1. 修改PoS类打开窗口的代码
class PoS: # ...其他代码 def open_custom_pizza(self): # 把add_custom_item方法作为回调传给窗口 CustomPizzaWindow(on_submit=self.add_custom_item)
2. 修改自定义披萨窗口类
class CustomPizzaWindow: def __init__(self, on_submit): self.on_submit = on_submit # 保存回调函数 self.win = tk.Toplevel() # ...窗口内的控件初始化 def submit(self): # 构建Item对象逻辑同上 self.custom_item = Item(000, name, self.total, 'Pizza') # 调用回调函数,传入Item对象 self.on_submit(self.custom_item) self.win.destroy()
3. PoS类的add_custom_item方法无需修改
和方案一里的方法保持一致即可。
这两种方案都能解决你的问题,方案一适合简单的小项目,方案二更适合复杂项目的解耦需求。
内容的提问来源于stack exchange,提问作者maxxslatt

