调用TopSoftwareWindow类内函数时触发AttributeError:'Toplevel'对象无'addtolist'属性
调用TopSoftwareWindow类内函数时触发AttributeError:'Toplevel'对象无'addtolist'属性
嗨,我看到你的问题了,这个报错的根源是你在__init__方法里错误地重新赋值了self变量,直接把类实例的指向给覆盖了,让我给你拆解问题和修复方案:
问题分析
你的TopSoftwareWindow类原本继承自ttk.Frame,但你在__init__的第一行就写了self = tk.Toplevel()——这会把原本指向TopSoftwareWindow类实例的self,直接替换成了一个原生的Toplevel对象。
而你定义的addtolist方法是属于TopSoftwareWindow类的,原生Toplevel对象根本没有这个方法,所以点击"New Entry"按钮调用self.addtolist时就会触发AttributeError,甚至因为self被覆盖,整个类的属性逻辑混乱,导致窗口都没法正常显示。
修复方案(直接继承Toplevel,最适合你的需求)
因为你的目标是做一个顶级窗口,直接让类继承tk.Toplevel是最合理的写法,不用再手动替换self:
import tkinter as tk from tkinter import ttk class TopSoftwareWindow(tk.Toplevel): # 改为继承tk.Toplevel def __init__(self, parent=None): # 增加parent参数,关联主窗口(Tkinter最佳实践) super().__init__(parent) # 调用父类初始化,正确创建Toplevel实例 self.geometry("800x600") self.resizable(False, False) self.title("Software Window") # 处理图标加载可能的异常(避免路径错误导致窗口崩溃) try: self.iconbitmap('MediaTracker_Icon.ico') except Exception as e: print(f"图标加载失败:{e}") # 窗口上的所有控件 self.Entry_Field = ttk.Entry(self) self.Text_List = tk.Listbox(self) self.Category_List = tk.Listbox(self) # 现在self是TopSoftwareWindow实例,能正常访问addtolist方法 self.New_Entry_Btn = ttk.Button(self, text="New Entry", command=self.addtolist) self.Save_File_Btn = ttk.Button(self, text="Save File") self.Load_File_Btn = ttk.Button(self, text="Load File") # 给Quit按钮添加关闭窗口的逻辑 self.Quit_Btn = ttk.Button(self, text="Quit", command=self.destroy) # 保持原布局不变 self.Entry_Field.place(x= 0, y= 0, width= 724) self.New_Entry_Btn.place(x= 725, y= 0) self.Text_List.place(x= 0, y= 25, width= 625, height= 570) self.Category_List.place(x= 626, y= 25, width= 99, height= 570) self.Save_File_Btn.place(x= 725, y= 25) self.Load_File_Btn.place(x= 725, y= 50) self.Quit_Btn.place(x= 725, y= 570) def addtolist(self): text = self.Entry_Field.get() if text: self.Text_List.insert(tk.END, text) self.Entry_Field.delete(0, tk.END) # 测试代码(如果需要单独运行这个窗口) if __name__ == "__main__": root = tk.Tk() root.withdraw() # 隐藏主窗口 app = TopSoftwareWindow(root) app.mainloop()
为什么这样改能解决问题
- 不再手动替换
self,self始终指向TopSoftwareWindow的实例,既拥有Toplevel的所有窗口功能,又能访问你自定义的addtolist方法。 - 用
super().__init__(parent)正确初始化父类,符合面向对象的继承逻辑。 - 增加
parent参数让窗口关联主窗口,避免出现无父级的孤立窗口。 - 给Quit按钮补充了关闭窗口的逻辑,提升用户体验。
可选:如果坚持继承Frame的写法
如果你因为某些原因必须继承ttk.Frame,可以把Frame嵌套在Toplevel里,而不是替换self:
class TopSoftwareWindow(ttk.Frame): def __init__(self, parent=None): self.top = tk.Toplevel(parent) # 创建顶级窗口 super().__init__(self.top) # 把Frame放在顶级窗口中 self.top.geometry("800x600") self.top.resizable(False, False) self.top.title("Software Window") # 后续控件的父容器可以用self(Frame)或self.top(顶级窗口) self.Entry_Field = ttk.Entry(self) self.New_Entry_Btn = ttk.Button(self, text="New Entry", command=self.addtolist) # 把Frame打包到顶级窗口 self.pack(fill=tk.BOTH, expand=True) # 剩余布局逻辑和addtolist方法保持不变...
不过这种写法比直接继承Toplevel复杂,对于你的需求来说,第一种方案更简单直接。
备注:内容来源于stack exchange,提问作者ThyKorey
相关产品推荐
相关产品推荐

