为什么root.quit()或root.destroy()不能正常工作,而只能同时使用两者?

时间:2019-05-17 11:45:42

标签: python tkinter

在我的程序中,我实现了一个弹出窗口,其中包含一些供用户输入的条目。该弹出窗口具有“输入”按钮,以确认并收集输入,然后自动关闭弹出窗口。 为了关闭弹出窗口,我找到了root.destroy()root.quit()方法(在我的代码self.master中而不是root中)。我以为我有点了解如何使用它们,但显然我没有。 :/


import tkinter as tk


root = tk.Tk()
window = MainWindow(root)
root.mainloop()


class MainWindow(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.pack()

        #some irrelevant widgets

        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()


    def new_element(self):

        root = tk.Toplevel()
        popup = Pupup(root, someData, otherData)
        root.mainloop()

        #do some other stuff



class Popup(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some widgets

        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a, b))
        btn.pack()


    def foo(self, a, b):

        #do something with widget data

        self.master.quit()
        self.master.destroy()

首先在foo()中,我只使用了destroy()。它关闭了弹出窗口,但是程序没有继续执行new_element()中的代码。 (似乎mainloop()仍在循环。) 使用quit()会产生相反的结果:new_element()中的其余代码已执行,但Popup仍然存在。 仅按照特定顺序使用quit()destroy()可以得到我想要的结果。

根据Internet上的数千个示例,应该仅可以使用两种方法之一。为什么在我的代码中不起作用?

编辑:从MainWindow构造函数中删除了var1和var2(在创建此问题期间复制并粘贴错误。

编辑:我也感觉到问题可能出在根杂草丛的范围上。在new_element()中创建一个名为root的局部变量还是覆盖全局根变量?

3 个答案:

答案 0 :(得分:2)

问题的根源在于您多次致电mainloop。你不应该那样做。它会引起很多问题,就像您遇到的问题一样。

如果您的目标是创建一个弹出窗口,然后等待用户关闭弹出窗口,则tkinter有专门用于此的方法。它称为wait_window,直到它正在等待的窗口被销毁,它才会返回。

top = tk.Toplevel()
popup = Popup(top, "some data", "other data")
top.wait_window(top)        

您可以在top.wait_window(top)之后放置其他代码,直到弹出窗口销毁后,该代码才会执行​​。

在您的弹出代码中,您的按钮只需要在弹出窗口中调用destroy。您不应致电quit

def foo(self, a, b):

    #do something with widget data

    self.master.destroy()

答案 1 :(得分:0)

您的示例有很多问题(复制粘贴不起作用),但是在安排了一些事情(赋予值和东西)后,这就是您的问题:

    def new_element(self):
        root = tk.Toplevel()
        popup = Pupup(root, someData, otherData)
        # root.mainloop() # < ------ This generates a new main loop, with is destroyed.

这是有效的完整代码:

import tkinter as tk


class Popup(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some widgets

        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a, b))
        btn.pack()


    def foo(self, a, b):

        #do something with widget data

        self.master.quit()
        # self.master.destroy()


class MainWindow(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some irrelevant widgets

        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()


    def new_element(self):

        root = tk.Toplevel()
        popup = Popup(root, 'a', 'b')
        # root.mainloop()

        #do some other stuff

root = tk.Tk()
window = MainWindow(root,1,2)
root.mainloop()

答案 2 :(得分:0)

我相信问题是您创建了第二个循环,要解决此问题,您只需删除第二个循环,然后.destroy()函数就可以正常工作。

class MainWindow(tk.Frame):
    def __init__():
        # your init code

    def new_element(self):
        root = tk.Toplevel()
        popup = Popup(root, 1, 0)

class Popup(tk.Frame):

    def __init__(self, master, var1, var2):
        # your init code

    def foo(self, a, b):
        self.master.destroy()

我将要发表的另一条评论是,我认为您构造此窗口的方式具有误导性,并且可能引起混乱(请记住,这只是偏好设置,不再涉及“实际”问题)。

我相信您应该创建一个Popup(Frame)类,而不要使用Popup(Toplevel)类。

import tkinter as tk

class MainWindow(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.pack()
        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()
        self.master = master
        self.pack()

    def new_element(self):
        popup = Popup(self.master, 1, 0)


class Popup(tk.Toplevel):
    def __init__(self, master, var1, var2):
        super().__init__(master)
        #some widgets
        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a,b))
        btn.pack()

    def foo(self, a, b):
        self.destroy()

if __name__ == '__main__':
    root = tk.Tk()
    window = MainWindow(root)
    root.mainloop()

创建顶级元素时,它需要一个母版,在此实例中,母版将成为主窗口。当您在Toplevel类中使用self.destroy时,您不是在破坏Toplevels主机,而是在破坏Toplevel本身。