【问题标题】:See if Tkinter widget exists (not using .winfo_exists)查看 Tkinter 小部件是否存在(不使用 .winfo_exists)
【发布时间】:2015-05-18 12:34:06
【问题描述】:

我想查看 Tkinter 小部件是否存在,如果存在,我可以将其删除。

此站点上的另一个answer 使用widget.winfo_exists,但即使小部件尚未创建,它也会返回1,并且仅在小部件已被销毁时才返回0

import Tkinter as tk
root = tk.Tk()
label = tk.Label(root)
print label.winfo_exists() # returns 1

和:

import Tkinter as tk
root = tk.Tk()
#label = tk.Label(root)
print label.winfo_exists() # also returns 1

而:

import Tkinter as tk
root = tk.Tk()
label = tk.Label(root)
label.destroy()
print label.winfo_exists() # returns 0

我试图以这种方式使用它:

import Tkinter as tk
root = tk.Tk()
# label may exist
if label.winfo_exists() == 1:
    label.destroy() # doesn't work

【问题讨论】:

  • 你确定吗?在您的第二种情况下,我希望NameError。另外,如果你尝试 re-destroy 一个小部件会有什么问题?
  • 如果一个小部件还没有创建,你怎么可能在它上面调用winfo_exists

标签: python tkinter


【解决方案1】:

您观察到winfo_exists() 为尚未创建的小部件返回1 是错误的。 python 的规则绝对会阻止你的场景以这种方式表现。

即:

$ python -i
Python 2.7.6 (default, Dec  2 2013, 11:20:48) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import Tkinter as tk
>>> root = tk.Tk()
>>> print label.winfo_exists()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'label' is not defined
>>> 

以上正是我所期望的。在这种情况下,您不可能让winfo_exists 返回1

“如何确定小部件是否存在”的正确答案是使用winfo_exists。这才是正确的方法。假设对象是或曾经是 Tkinter 小部件类的实例,它将始终有效。

【讨论】:

  • 是的,看来我很困惑。当我仔细检查时,我一定犯了一个错误!感谢您解决这个问题。
【解决方案2】:

您似乎对保存对 Tk 小部件的引用的 Python 变量和 Tk 窗口本身感到困惑。 winfo_exists 仅在 Tk 小部件有窗口时才返回 true。在您销毁小部件后,python 变量可能会继续存在,在这种情况下,winfo_exists 将返回 false。

由于 Tk destroy 函数在调用已销毁的小部件时不会引发错误,因此您应该能够在不进行任何检查的情况下调用它。但是,您确实需要一个值 python 变量,该变量最初包含一个 Tk 小部件。

下面的交互式会话应该会展示这一点:

>>> from tkinter import *
>>> root = Tk()
>>> label = Label(root)
>>> label.destroy()
>>> label
<tkinter.Label object at 0x02B88310>
>>> label.destroy()
>>> label.winfo_exists()
0

在此示例中,标签小部件会立即创建和销毁。这留下了一个 Python 对象,我们可以在其上调用 winfo_exists 并且它正确返回 false。另请注意,label.destroy() 被调用了两次,没有任何不良影响。

【讨论】:

    【解决方案3】:

    我一直使用try / except,而except: pass 通常不受欢迎,但在这里可以使用。

    try:
        label.destroy()
    except (NameError, AttributeError):
        pass
    

    还有:

    import Tkinter as tk
    root = tk.Tk()
    #label = tk.Label(root)
    print label.winfo_exists() # also returns 1
    

    这不会返回 1,因为 label 未定义,所以它不可能有 winfo_exists()

    【讨论】:

    • 您至少可以在except 上更加明确 - 如果label 不能是destroyed 会抛出什么?
    • 好吧,他可以根据具体情况点击NameErrorAttributeError...如果他想简单地destroy() 小部件,如果可能的话,这真的意味着要抓住一切。
    • 那么它应该是except (NameError, AttributeError),或者绝对最小值 except Exception,以避免干扰例如KeyboardInterrupt.
    猜你喜欢
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 2015-05-14
    • 1970-01-01
    相关资源
    最近更新 更多