在单独的函数中删除 Tkinter 对象(在函数中创建)

Removing Tkinter Objects (created in a function) in a separate function

我需要能够清除所有对象(带有函数)的 tkinter window,然后使用函数再次创建对象。但是,我无法使用第二个函数访问用第一个函数创建的对象。我在下面重现了我的问题。

import tkinter
window = tkinter.Tk()
def create():
    test = tkinter.Button(window, text="Example", command=delete)
    test.place(x=75, y=100)

def delete():
    test.place_forget()

create()
window.mainloop()

这个returns错误-NameError: name 'test' is not defined

好吧,如果您使用两个不同的函数,您将需要 global 个变量:

import tkinter
window = tkinter.Tk()

test = None

def create():
    global test
    test = tkinter.Button(window, text="Example", command=delete)
    test.place(x=75, y=100)

def delete():
    global test
    test.destroy() # or place_forget if you want
    window.after(5000, create) # button reappears after 5 seconds

create()
window.mainloop()

您的 delete 函数无法破坏按钮,因为它仅在 create 函数中定义。解决方法是创建一个全局变量,两者都可以访问。

下面是使用面向对象结构的代码外观的快速示例:

import tkinter as tk

class MyApp: # No need to inherit 'object' in Python 3
    def __init__(self, root):
        self.root = root

    def create_button(self):
        self.test_button = tk.Button(self.root,
                text="Example",
                command=self.delete_button)
        self.test_button.place(x=75, y=100)

    def delete_button(self):
        self.test_button.place_forget()

    def run(self):
        self.create_button()
        self.root.mainloop()


if __name__=='__main__':
    root = tk.Tk()
    app = MyApp(root)
    app.run()

您创建一个 MyApp 对象,该对象 'owns' 按钮,并具有明确作用于它所拥有的事物的方法。 MyApp 对象的任何方法都有对各种小部件的引用,通过自动发送的 self 参数。

这比您以前的代码多得多,老实说,对于您的代码现在所做的事情,这是一种矫枉过正。 Malik 使用 global 的解决方案可能没问题。但是,如果您想添加更多小部件,将它们分层,让它们以更复杂的方式进行交互等,那么使用 global 可能会引入难以发现的错误,并使您难以理解到底是什么进行中。

我见过的任何对 Tkinter 的重要使用都使用了类似于上述示例的面向对象的风格。

顺便说一句,我不会创建 delete 函数 - 在创建按钮后使用 .config 方法设置命令会更好:

def create_button(self):
    self.test_button = tk.Button(self.root, text="Example")
    self.test_button.config(command=self.test_button.place_forget)
    self.test_button.place(x=75, y=100)

使用 .config 允许您设置命令,这些命令是您刚创建的按钮的方法,当您将命令设置为按钮实例化的一部分时,您不能这样做。