首页 > 解决方案 > 在 tkinter 中创建模式对话框

问题描述

这个问题不是重复的:见下文。

我想在 tkinter 中创建一个模式对话框。换句话说,一个对话框,当它处于活动状态时,会阻止用户与父窗口交互。有一个关于 SO 回答这个问题的现有问题,并且有一个完整的例子来说明这个概念。

但是,在 Windows 7 或 Ubuntu 16.04.4 LTS 上,将对话框设置为 Toplevel 并在其上调用 grab_set() 根本不起作用。用户仍然可以关闭、调整大小并与父窗口进行交互。

有没有办法在 Tkinter 中创建一个真正有效的模式对话框?

这是 dialog.grab_set() 未能阻止与父窗口交互的最小用法示例:

import os
try:
    import Tkinter as tkinter
except ImportError:
    import tkinter

class MyToplevel(tkinter.Toplevel, object):
    def __init__(self, parent):
        tkinter.Toplevel.__init__(self, parent)

        self.title("Main window")
        MyDialog(self)

        self.protocol("WM_DELETE_WINDOW", parent.destroy)

class MyDialog(tkinter.Toplevel, object):
    def __init__(self, parent):
        tkinter.Toplevel.__init__(self, parent)

        self.transient(parent)
        self.title("Dialog")
        self.grab_set()

        self.protocol("WM_DELETE_WINDOW", self.destroy)

if __name__ == "__main__":
    root = tkinter.Tk()
    root.withdraw()
    app = MyToplevel(root)
    app.mainloop()

我应该指出,使用 grab_set_global() (如在这个答案中)确实有效,但不是一个可行的解决方案,因为它会阻止对整个系统的所有窗口的访问。

标签: pythontkinterdialogmodal-dialogpython-2.x

解决方案


这是(至少在 Windows 上)一个特定于版本的问题。要使其正常工作python2.7,只需在self.focus_force()之前添加self.grab_set()

def __init__(self, parent):
    tkinter.Toplevel.__init__(self, parent)

    self.transient(parent)
    self.title("Dialog")

    self.focus_force() # added
    self.grab_set()

    self.protocol("WM_DELETE_WINDOW", self.destroy)

推荐阅读