关于tkinter的w.destroy()方法未彻底清除Widget对象的技术问询
Tkinter组件destroy()方法未彻底清除Python对象的疑问
我在Python解释器中执行以下命令后发现,tkinter组件的w.destroy()方法并未彻底清除该组件在Python中的对象引用:
>>> root=tk.Tk() >>> a = ttk.Button(root, text="Button") >>> a.grid(row=0, column=0) >>> a <tkinter.ttk.Button object .!button> >>> a.destroy() >>> a <tkinter.ttk.Button object .!button> >>> a.grid(row=0, column=0) Traceback (most recent call last): File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode exec(code, self.locals) File "<pyshell#23>", line 1, in <module> File "/usr/lib/python3.10/tkinter/__init__.py", line 2522, in grid_configure self.tk.call( _tkinter.TclError: bad window path name ".!button" >>> b Traceback (most recent call last): File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode exec(code, self.locals) File "<pyshell#24>", line 1, in <module> NameError: name 'b' is not defined >>> del a >>> a Traceback (most recent call last): File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode exec(code, self.locals) File "<pyshell#26>", line 1, in <module> NameError: name 'a' is not defined >>> root.destroy() >>> root <tkinter.Tk object .> >>> del root >>> root Traceback (most recent call last): File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode exec(code, self.locals) File "<pyshell#30>", line 1, in <module> NameError: name 'root' is not defined >>>
根据tkinter官方文档描述:
w.destroy()
Calling w.destroy() on a widget w destroys w and all its children.
在上述测试中,调用a.destroy()后,按钮确实从界面消失,且无法再执行任何tkinter相关方法(会抛出_tkinter.TclError),但Python解释器仍然将a识别为<tkinter.ttk.Button object .!button>对象,只有执行del a后,再调用a才会触发NameError。root.destroy()也存在同样的现象。
我认为tkinter的维护者应该在.destroy()方法中加入del w逻辑(w指代任意tkinter组件),否则用户每次调用w.destroy()后都要手动执行del w来保证代码整洁。请问这个思路是否合理?
以下是我自己实现的一个类方法示例,用来清除类属性中的组件引用:
>>> class App(tk.Frame): def __init__(self, master, **kw): super().__init__(master, bg="pink") self.master = master self.bn = tk.Button(self, text="Button", bg="cyan", width=10, height=2) self.bn.grid(row=0, column=0) def eradicate(self): del self.bn >>> root = tk.Tk() >>> root.geometry("150x150+10+10") '' >>> app = App(root) >>> app.grid(row=0, column=0) >>> root.columnconfigure(0, weight=1) >>> root.rowconfigure(0, weight=1) >>> app.eradicate() >>> app.bn Traceback (most recent call last): File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode exec(code, self.locals) File "<pyshell#116>", line 1, in <module> AttributeError: 'App' object has no attribute 'bn'
内容的提问来源于stack exchange,提问作者Sun Bear
相关产品推荐
相关产品推荐

