如何确定 tkinter Toplevel 小部件是否存在?

huangapple go评论72阅读模式
英文:

How to determine if tkinter Toplevel widget exists.?

问题

Sure, here is the translated code:

我有一个需要在创建 `Toplevel` 窗口之前销毁它如果已经存在的需求我已经研究过这个问题无论是在这里还是其他地方每一个回答都建议使用 `winfo_exists` 方法然而下面的代码演示了它不起作用它会出现错误对象没有属性 'toplevel'

我可以使用粗暴的 try:/except: 方法来销毁窗口但肯定有更好的方法

顺便说一下我在运行 Python 3.11.1 的 Windows 10

```python
# does_widget_exist.py

import tkinter as tk

class TL_GUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.geometry('300x100')
        self.root.title('Tkinter Test')
        button0 = tk.Button(self.root, text='创建 Toplevel', command=self.makeToplevel)
        button0.pack(pady=20)
        self.toplevel = None
        self.root.mainloop()

    def makeToplevel(self):
        if self.toplevel and self.toplevel.winfo_exists():
            self.toplevel.destroy()
        self.toplevel = tk.Toplevel(self.root)
        self.toplevel.geometry('500x100')
        self.toplevel.title('我是一个 TopLevel')
        text0 = tk.Label(self.toplevel, text='你好,世界', height=1, width=25, borderwidth=5)
        text0.pack()

if __name__ == '__main__':
    TL_GUI()

I hope this helps. If you have any other questions or need further assistance, please let me know.

英文:

I have a need to destroy a Toplevel widget if it already exists before creating it. I've researched this and every response I can find here and elsewhere suggest using winfo_exists; however, the following code demonstrates that doesn't work. It fails with the error: object has no attribute 'toplevel'

I can use a brute force try:/except: to destroy the widget, but surely there's a better way.

BTW: I am on Windows 10 running Python 3.11.1

# does_widger_exists.py

import tkinter as tk


class TL_GUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.geometry('300x100')
        self.root.title('Tkinter Test')
        button0 = tk.Button(self.root,text='Create Toplevel',command=self.makeToplevel).pack(pady=20)
        self.root.mainloop()
 
    def makeToplevel(self):
        if tk.Toplevel.winfo_exists(self.toplevel):
            self.toplevel.destroy()
        self.toplevel = tk.Toplevel(self.root)
        self.toplevel.geometry('500x100')
        self.toplevel.title('I am a TopLevel')
        text0 = tk.Label(self.toplevel,text='Hello World',height=1,width=25,borderwidth=5).pack()
 

if __name__ == '__main__':
    TL_GUI()

答案1

得分: 1

你需要在你的__init__方法中初始化self.toplevel为某个值,这样第一次调用makeToplevel时,当进入条件语句时不会失败;如代码所示,当首次运行检查时,self.toplevel不存在。有了这个修复,后续对makeToplevel的调用将按预期工作。

def __init__(self):
    self.root = tk.Tk()
    self.root.geometry('300x100')
    self.root.title('Tkinter Test')

    self.toplevel = None  # 初始化这个实例变量

    button0 = tk.Button(
        self.root,
        text='Create Toplevel',
        command=self.makeToplevel
    ).pack(pady=20)
    self.root.mainloop()

你还应该按以下方式更新if语句检查的条件:

def makeToplevel(self):
    if self.toplevel and self.toplevel.winfo_exists():  # 做这个更改
        self.toplevel.destroy()
    self.toplevel = tk.Toplevel(self.root)
    self.toplevel.geometry('500x100')
    self.toplevel.title('I am a TopLevel')
    text0 = tk.Label(
        self.toplevel,
        text='Hello World',
        height=1,
        width=25,
        borderwidth=5
    ).pack()

另外,最后要注意一点:像你在button0text0上使用的pack()会在不小心的情况下引发问题!如代码所示,button0text0都将始终评估为None,因为这是pack()返回的值。如果你想在其他地方引用这些小部件,应该将它们分开pack()到另一行,例如:

button0 = tk.Button(...)  # 现在 'button0' 等于 Button 对象,而不是 None
button0.pack(...)

text0 = tk.Label(...)  # 现在 'text0' 等于 Label 对象,而不是 None
text0.pack(...)
英文:

You'll need to initialize self.toplevel to some value in your __init__ method so the first call to makeToplevel doesn't fail when it gets to the conditional; as written, self.toplevel doesn't exist when the check is first run. With this fix, subsequent calls to makeToplevel will work as expected

def __init__(self):
    self.root = tk.Tk()
    self.root.geometry('300x100')
    self.root.title('Tkinter Test')

    self.toplevel = None  # initialize this instance variable

    button0 = tk.Button(
        self.root,
        text='Create Toplevel',
        command=self.makeToplevel
    ).pack(pady=20)
    self.root.mainloop()

You should also update the condition checked by the if statement as follows:

def makeToplevel(self):
    if self.toplevel and self.toplevel.winfo_exists():  # make this change
        self.toplevel.destroy()
    self.toplevel = tk.Toplevel(self.root)
    self.toplevel.geometry('500x100')
    self.toplevel.title('I am a TopLevel')
    text0 = tk.Label(
        self.toplevel,
        text='Hello World',
        height=1,
        width=25,
        borderwidth=5
    ).pack()

Oh, and one final note: using pack() like you are on button0 and text0 can cause trouble if you're not careful! As written, button0 and text0 will both always evaluate to None since that's the value returned by pack(). If you want to refer to these widgets anywhere else, you should pack() them on a separate line, e.g.:

button0 = tk.Button(...)  # now 'button0' is equal to the Button object, not None
button0.pack(...)

text0 = tk.Label(...)  # now 'text0' is equal to the Label object, not None
text0.pack(...)

huangapple
  • 本文由 发表于 2023年3月7日 23:40:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75664091.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定