如何在子窗口关闭之前防止关闭父窗口

时间:2017-06-13 16:15:48

标签: python tkinter ubuntu-16.04

我知道,来自here

  

grab_set()[#]:   将此应用程序的所有事件路由到此窗口小部件。

好的,但它不会阻止用户使用X按钮关闭父窗口。除了其他事件,我如何路由" X按钮关闭"事件也是?

MWE:

from Tkinter import *

class Window(Toplevel):

    def __init__(self, master):
        Toplevel.__init__(self)


class MainWindow(Tk):

    def __init__(self):
        Tk.__init__(self)
        Button(self, command=self.open_window).grid(row=0, column=0)

    def open_window(self):
        win = Window(self)
        win.grab_set()


app = MainWindow()
app.mainloop()

2 个答案:

答案 0 :(得分:1)

对于Windows,您可以使用:

root.protocol("WM_DELETE_WINDOW", your_function_here)

我不了解其他操作系统,因为我没有在Windows以外的任何其他设备上进行测试。

在课堂上也能正常工作。

self.root.protocol("WM_DELETE_WINDOW", self.your_method_here)

我在帖子中添加了一些代码来说明其用法。请注意,当您按下X按钮时,程序将使用close_program方法。

编辑:如果无法在Mac上测试,我已经添加了我认为可以解决问题的方法。我在close_program方法中添加了一个if语句,以便在尝试关闭之前检查顶级是否存在。

更新:我添加了变量win的检查,以处理可能的错误,如果toplevel从未打开但仍尝试关闭根窗口。

from tkinter import *

class Window(Toplevel):

    def __init__(self, master):
        Toplevel.__init__(self)
        self.protocol("WM_DELETE_WINDOW", self.close_program)

    def close_program(self):
        print ("destroying Window")
        self.destroy()


class MainWindow(Tk):

    def __init__(self):
        Tk.__init__(self)
        Button(self, command=self.open_window).grid(row=0, column=0)
        self.protocol("WM_DELETE_WINDOW", self.close_program)

    def open_window(self):
        global win
        win = Window(self)
        win.grab_set()

    def close_program(self):
        if 'win' in globals():
            if win.winfo_exists() == 1:
                print("top level still active")
            else:
                print("destroying MainWindow")
                self.destroy()
        else:
            print("destroying MainWindow")
            self.destroy()


app = MainWindow()
app.mainloop()

答案 1 :(得分:1)

让我们假设如果子窗口存在,尝试关闭父窗口会使其成为焦点,这需要进行一些更改:

  1. 使用.protocol("WM_DELETE_WINDOW")覆盖关闭协议,以便检查子窗口。
  2. 保留对子窗口的引用
  3. class MainWindow(Tk):
    
        def __init__(self):
            Tk.__init__(self)
            Button(self, text="hello there", command=self.open_window).grid(row=0, column=0)
            self.protocol("WM_DELETE_WINDOW", self.try_to_close)
            self.win = None
    
        def open_window(self):
            if self.win is None or not self.win.winfo_exists():
                self.win = Window(self)
            self.win.lift(self)
            self.win.focus_set()
    
        def try_to_close(self):
            if self.win is not None and self.win.winfo_exists():
                self.win.lift()
            else:
                self.destroy()