Python Tkinter类间调用报__init__缺失parent参数错误如何解决?
错误根因
报错的核心是chk_file_exist方法中的Leftframe().update_listbox()写法错误:该代码是尝试新建一个Leftframe类的实例,而非调用已经渲染到主窗口上的现有Leftframe实例。Leftframe的构造方法强制要求传入parent父容器参数,新建实例时未传参就触发了参数缺失报错。
架构说明
拆分Frame类的开发方式完全符合Tkinter面向对象开发的最佳实践,不需要改为单窗口类,也不需要把所有组件集成到同一个类中,仅需要调整两个Frame实例的引用逻辑即可。
修复方案
核心逻辑是让Rightframe持有已创建的Leftframe实例的引用,直接调用已有实例的方法,无需新建实例。修改后的完整可运行代码如下:
import tkinter as tk import os class Leftframe(tk.Frame): def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.scrollbar = tk.Scrollbar(self) self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.mylist = tk.Listbox(self, yscrollcommand=self.scrollbar.set) self.mylist.place(x=0, y=0, width=260, height=410) self.scrollbar.config(command=self.mylist.yview) self.empty_listbox() def empty_listbox(self): self.mylist.delete(0, tk.END) for it in ([' ']): self.mylist.insert(tk.END, it) def update_listbox(self): self.mylist.delete(0, tk.END) # 此处保留原有解析文件更新列表的逻辑 # for it in parsedlist: # self.mylist.insert(tk.END, it) class Rightframe(tk.Frame): # 新增left_frame初始化参数,接收左面板实例 def __init__(self, parent, left_frame, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.left_frame = left_frame # 保存左面板实例引用 self.start_btn = tk.Button(self,text='Start') self.start_btn.config(command=self.button_start_push) self.start_btn.place(anchor=tk.NW,x=10,y=10,width=60,height=20) self.stop_btn = tk.Button(self,text='Stop') self.stop_btn['state'] = tk.DISABLED self.stop_btn.config(command=self.button_stop_push) self.stop_btn.place(anchor=tk.NW,x=10,y=60,width=60,height=20) def chk_file_exist(self): if 1:#os.path.isfile(os.path.join(os.curdir, fileroute)): 调试强制为真 # 调用已有左面板实例的更新方法,不再新建实例 self.left_frame.update_listbox() else: print('file generating, please wait')#后台脚本生成文件中 main_win.after(1000, self.chk_file_exist) def button_start_push(self): print('Started') self.start_btn['state'] = tk.DISABLED self.stop_btn['state'] = tk.NORMAL global fileroute self.chk_file_exist() def button_stop_push(self): print('stop button pressed') self.start_btn['state'] = tk.NORMAL open(os.path.join(os.curdir, 'stop.txt'), 'a').close() if __name__ == '__main__': fileroute = 'XXX.pkl' main_win = tk.Tk() main_win.geometry("200x150+0+0") # 先实例化左面板,保存为变量 left_panel = Leftframe(main_win, relief="sunken", borderwidth=1) left_panel.place(x=10, y=10, width=80, height=100) # 实例化右面板时传入左面板实例 right_panel = Rightframe(main_win, left_frame=left_panel, relief="sunken", borderwidth=1) right_panel.place(x=100, y=10, width=80, height=100) main_win.mainloop()
如果不想通过初始化参数传引用,也可以将两个面板实例绑定到主窗口对象上,在Rightframe中通过self.parent.left_panel访问对应实例,效果一致。
内容的提问来源于stack exchange,提问作者roberto
相关产品推荐
相关产品推荐

