`w.destroy()`方法不会根除`tkinter`小部件?

问题描述 投票:0回答:1

我在Python解释器中提交了以下命令,发现

w.destroy()
小部件的
tkinter
方法并没有根除(即消除其存在)
tkinter
小部件。

>>> 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
>>> 

引用文档

w.destroy()
Calling w.destroy() on a widget w destroys w and all its children.

在上面的例子中,虽然

a.destroy()
确实移除了
ttk.Button
的外观并且不让
a
运行其他tkinter方法,但是
a
仍然被识别为
<tkinter.ttk.Button object .!button>
对象,即
a的存在
并没有从 Python 解释器中消失。仅在通过
a
命令删除
del a
后,才会在调用
NameError: name 'a' is not defined
时引发
a
异常。在
root.destroy()
中可以看到相同的结果。

我认为

tkinter
包维护者需要在其
del w
方法中包含
w
命令(这里,
.destroy()
指任何 tkinter 小部件)。如果没有,tkinter 用户目前需要在每个
del w
方法之后运行
w.destroy()
命令,以确保 Python 代码的整洁。我的推理合理吗?

按照我评论中的想法,下面是消除类属性的类方法的示例:

>>> 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'
python tkinter tcl
1个回答
0
投票

我认为 tkinter 包维护者需要在其 .destroy() 方法中包含一个 del w 命令(这里,w 指任何 tkinter 小部件)。如果没有,tkinter 用户目前需要在每个 w.destroy() 方法之后运行 del w 命令,以确保其 Python 代码的整洁。我的推理合理吗?

不,你的推理不合理。对象不能销毁引用该对象的变量。例如,一个对象可以被多个变量引用,代码应该如何知道要销毁哪个变量?如果您不希望引用被破坏怎么办?在某些用例中,即使小部件本身已被销毁,您也希望保留引用。

几乎不需要在保存对小部件的引用的变量上调用

del
。当 Python 检测到不再使用这些对象时,它能够自动销毁这些对象(称为垃圾收集器)。

© www.soinside.com 2019 - 2024. All rights reserved.