【问题标题】:Closing main window from toplevel window with tkinter in python在python中使用tkinter从顶层窗口关闭主窗口
【发布时间】:2017-04-21 15:22:30
【问题描述】:

这是我的第一个问题,我是 python 和这个网站的新手。

我正在设计一个与数据库交互的应用程序。我添加了一个“关闭”按钮,我想打开一个新窗口询问“关闭程序?”和 2 个按钮:是和否。当您单击否时,新窗口将关闭。当您单击“是”时,两个窗口都会关闭。

我的代码可以正常工作,但我很确定有更好或更智能的方法。

为了让它工作,我必须在“close_window”方法中编写“root.destroy()”,但我很确定有一种更聪明的方法可以使用类似“self.master.destroy()”的方法获得相同的结果" 它使用了 python 的所有功能。我在下面展示了一个简化版本的代码。

提前致谢。

阿方索

from tkinter import *

class Window():

    def __init__(self, main):
        self.main = main

        self.b5=Button(self.main, text="Action 1", width=12)
        self.b5.grid(row=0, column=1)

        self.b5=Button(self.main, text="Action 2", width=12)
        self.b5.grid(row=0, column=2)

        self.b6=Button(self.main, text="Close", width=12, command=self.new_window)
        self.b6.grid(row=0, column=3)

    def new_window(self):
        self.newWindow = Toplevel(self.main)
        self.app = Demo2(self.newWindow)

    def close_window(self):
        root.destroy()


class Demo2:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)

        self.l1=Label(self.frame, text="Close the program?")
        self.l1.grid(row=0, column=0, columnspan=2)

        self.b1=Button(self.frame, text="Yes", command=self.yes_com)
        self.b1.grid(row=1, column=0)

        self.b1=Button(self.frame, text="No", command=self.no_com)
        self.b1.grid(row=1, column=1)

        self.frame.pack()

    def yes_com(self):
        self.master.destroy()
        Window.close_window(self)

    def no_com(self):
        self.master.destroy()


def main():
    global root
    root = Tk()
    app = Window(root)
    root.mainloop()

if __name__ == '__main__':
    main()

【问题讨论】:

    标签: python python-3.x tkinter


    【解决方案1】:

    您可以简单地使用messagebox 模块提供的标准对话框。

    具体来说,它提供了askyesno 对话框,负责打开/关闭新窗口,如果用户单击Yes,则返回True,如果用户单击No,则返回False。然后,您可以简单地使用if-statement 来关闭窗口,如果用户这么说,只需使用self.main.destroy()(无需将root 声明为global)。

    from tkinter import *
    from tkinter import messagebox
    
    class Window():
    
        def __init__(self, main):
            self.main = main
    
            self.b5=Button(self.main, text="Action 1", width=12)
            self.b5.grid(row=0, column=1)
    
            self.b5=Button(self.main, text="Action 2", width=12)
            self.b5.grid(row=0, column=2)
    
            self.b6=Button(self.main, text="Close", width=12, command=self.close_window)
            self.b6.grid(row=0, column=3)
    
        def close_window(self):
            if messagebox.askyesno('Close', 'Close the program?'):
                self.main.destroy()
    
    def main():
        root = Tk()
        app = Window(root)
        root.mainloop()
    
    if __name__ == '__main__':
        main()
    

    备注

    1. 标准对话框中的是/否按钮是本地化的,这意味着它们被翻译成您的计算机设置使用的语言。
    2. 如果您查看messagebox 模块,您会发现还有其他标准对话框。恕我直言,在这种情况下,我会使用 askyescancel,它的使用方式完全相同,但看起来更语义化。

    【讨论】:

    • 谢谢皮尔保罗。 messagebox 模块正是我所需要的。如果我可能会问,如果我已经使用 from tkinter import * 导入整个 tkinter 库,为什么还需要 from tkinter import messagebox?再次感谢您的帮助!
    • @Alfonso:那是因为from my_package import *导入my_module 中的所有内容,而只导入该包决定导出的内容。在这种情况下,messagebox 不会自动导入,因为 tkinter 模块没有显式导出它,因此您必须手动执行。如需更深入的解释,请查看Why import * and then ttk?,它解决了相同的问题,但在这种情况下,模块是ttk 而不是messagebox
    • 感谢您的回答!
    【解决方案2】:

    Pier Paolo 有正确的答案,但为了科学起见,以下是您问题的直接答案:

    def yes_com(self):
        self.master.master.destroy() # <this class instance>.<toplevel instance>.<Tk instance>.destroy()
    

    或者你可以简单地退出 python:

    import sys
    
    def yes_com(self):
        sys.exit()
    

    【讨论】:

    • 使用sys.exit() 很好;仅使用普通的 exit()quit() 取决于安装,因此您不应在代码中使用它。纯版本可用于 REPL。
    • 对不起,我对您的代码做了一个快速的假设。已编辑。
    • 您好乔纳森,感谢您的建议。 sys.exit() 工作正常并关闭所有内容。我在这里有一个问题,有人告诉我销毁 tkinter 窗口比 quit()exit() 更好。你怎么看? self.master.main.destroy() 没有工作,出现以下错误:self.master.main.destroy() AttributeError: 'Toplevel' object has no attribute 'main' 知道为什么吗?我想了解链接这两个类的方式。再次感谢您的帮助!
    • self.master.master.destroy() 有效。感谢您的解释性评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多