Python 如何在TkInter中激活模式对话框时禁用窗口控件?

Python 如何在TkInter中激活模式对话框时禁用窗口控件?,python,tkinter,modal-dialog,Python,Tkinter,Modal Dialog,我正在用TkInter编写一个Python应用程序。在某个点上,应用程序(root)会显示一个对话框(dlg,它是一个Toplevel)。为了使对话框成为模态,我使用以下代码: dlg.focus_set() dlg.grab_set() dlg.transient(root) root.wait_window(dlg) 这确实会取消对话框外的“自定义”事件(如主应用程序窗口中的小部件),但不会取消窗口管理器事件,因此,例如,单击主应用程序窗口可以使其重新聚焦,并且可以移动、调整大小,甚至关闭

我正在用TkInter编写一个Python应用程序。在某个点上,应用程序(
root
)会显示一个对话框(
dlg
,它是一个
Toplevel
)。为了使对话框成为模态,我使用以下代码:

dlg.focus_set()
dlg.grab_set()
dlg.transient(root)
root.wait_window(dlg)
这确实会取消对话框外的“自定义”事件(如主应用程序窗口中的小部件),但不会取消窗口管理器事件,因此,例如,单击主应用程序窗口可以使其重新聚焦,并且可以移动、调整大小,甚至关闭!-当“模态”对话框仍然打开时

如何使对话框真正成为模态,以便在对话框处于活动状态时,主应用程序窗口的窗口管理器事件也被挂起


我正在Ubuntu 15.04上使用Python 3.4.3。

您可以使用root.grab\u set\u global(),如本例所示:

import Tkinter
class Application(Tkinter.Frame):
    def mygrab(self):
        print "grab is ok"
        root.grab_set_global()

    def createWidgets(self):
        self.QUIT = Tkinter.Button(self)
        self.QUIT["text"] = "QUIT"
        self.QUIT["command"] =  self.quit
        self.QUIT.pack({"side": "left"})
        self.grab = Tkinter.Button(self)
        self.grab["text"] = "Grab",
        self.grab["command"] = self.mygrab
        self.grab.pack({"side": "left"})        

    def __init__(self, master=None):
        Tkinter.Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

root = Tkinter.Tk()
app = Application(master=root)
app.mainloop()
root.destroy()`

您可以使用root.grab\u set\u global(),如下例所示:

import Tkinter
class Application(Tkinter.Frame):
    def mygrab(self):
        print "grab is ok"
        root.grab_set_global()

    def createWidgets(self):
        self.QUIT = Tkinter.Button(self)
        self.QUIT["text"] = "QUIT"
        self.QUIT["command"] =  self.quit
        self.QUIT.pack({"side": "left"})
        self.grab = Tkinter.Button(self)
        self.grab["text"] = "Grab",
        self.grab["command"] = self.mygrab
        self.grab.pack({"side": "left"})        

    def __init__(self, master=None):
        Tkinter.Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

root = Tkinter.Tk()
app = Application(master=root)
app.mainloop()
root.destroy()`
试着这样做:

dlg.focus_set()
dlg.grab_set()
dlg.transient(root)
dlg.wait_window(dlg)
试着这样做:

dlg.focus_set()
dlg.grab_set()
dlg.transient(root)
dlg.wait_window(dlg)

grab_set_global会导致整个计算机冻结(我不明白操作系统是如何允许的)。这绝对不是答案!在答案被编辑后:我特别提到我在Python 3上;您的代码是Python2。此外,grab_set_global“抓取”整个系统,而不仅仅是应用程序内部。这不是我想要的(我仍然不明白操作系统是如何允许的)。在模式对话框中,通常禁用对话框外的所有交互。如果你想禁用窗口管理器,除了它,你没有其他解决方案,但是在你退出对话框窗口之前,其他窗口交互也会被禁用。这不是我想要的解决方案,因为我不可能使整个系统瘫痪。同样,我不明白为什么这是一个选择。基本上,你所说的是我想要的,但我做不到的-你能参考一些源代码吗?在Unix和ubuntu上,有XWindowsSystem的O'Reilly文档。我的回答只涉及Unix,而不涉及Windows。在Unix上,您可能可以在有关窗口管理器的文档中找到它。在某些应用程序上,可以删除窗口管理器,并且没有标题栏和边框;这在windows中是不可能的。grab\u set\u global会导致整个计算机冻结(我不明白操作系统是如何允许的)。这绝对不是答案!在答案被编辑后:我特别提到我在Python 3上;您的代码是Python2。此外,grab_set_global“抓取”整个系统,而不仅仅是应用程序内部。这不是我想要的(我仍然不明白操作系统是如何允许的)。在模式对话框中,通常禁用对话框外的所有交互。如果你想禁用窗口管理器,除了它,你没有其他解决方案,但是在你退出对话框窗口之前,其他窗口交互也会被禁用。这不是我想要的解决方案,因为我不可能使整个系统瘫痪。同样,我不明白为什么这是一个选择。基本上,你所说的是我想要的,但我做不到的-你能参考一些源代码吗?在Unix和ubuntu上,有XWindowsSystem的O'Reilly文档。我的回答只涉及Unix,而不涉及Windows。在Unix上,您可能可以在有关窗口管理器的文档中找到它。在某些应用程序上,可以删除窗口管理器,并且没有标题栏和边框;windows无法执行此操作。是否确实要禁用与窗口管理器的交互?与其禁用它,通常更好的答案是做好处理它的准备。例如,关闭对话框窗口的操作应与单击“取消”相同(假设对话框中有“取消”按钮)。毕竟,如果用户真的想关闭窗口,应该允许他们关闭。谢谢你的评论,@Bryan。请注意,我不是要为对话框禁用窗口管理器,而是要为主应用程序窗口禁用窗口管理器。我所描述的正是标准行为;应该允许用户关闭对话框,但不能在对话框仍处于活动状态时关闭整个应用程序。为什么不允许用户关闭整个应用程序?让他们这么做有什么不对,如果他们想这么做的话?我们可以讨论一下,布莱恩,但这不是眼下的问题。这是标准行为,不是我发明的。当对话框打开时,应用程序的其余部分将“瘫痪”——包括窗口控件。不管这是否合理,这是标准,这就是我想要的。(作为一个用例,假设退出时出现一个“退出前是否保存?”对话框。当此对话框打开时,用户无法再次尝试退出,这是没有意义的,对吗?)是否确实要禁用与窗口管理器的交互?与其禁用它,通常更好的答案是做好处理它的准备。例如,关闭对话框窗口的操作应与单击“取消”相同(假设对话框中有“取消”按钮)。毕竟,如果用户真的想关闭窗口,应该允许他们关闭。谢谢你的评论,@Bryan。请注意,我不是要为对话框禁用窗口管理器,而是要为主应用程序窗口禁用窗口管理器。我所描述的正是标准行为;应该允许用户关闭对话框,但不能在对话框仍处于活动状态时关闭整个应用程序。为什么不允许用户关闭整个应用程序?让他们这么做有什么不对,如果他们想这么做的话?我们可以讨论一下,布莱恩,但这不是眼下的问题。这是标准行为,不是我发明的。当对话框打开时,应用程序的其余部分将“瘫痪”——包括窗口控件。不管这是否合理,这是标准,这就是我想要的。(作为唯一的一个用例,假设退出时出现一个“您想在退出前保存吗?”对话框。它不会使