阻止输入对话框

Blocking Input Dialog Box

如何在标准 Python 中获得阻塞模态输入对话框?

我需要用户输入一个值才能继续执行代码。

这是一些不工作测试代码,但我的想法是我应该能够从脚本中的任何地方调用MyDialog,所以这只是一个简化的例子。

import tkinter

class MyDialog:
    def __init__(self, prompt):
        self.top = tkinter.Toplevel()
        tkinter.Label(self.top, text=prompt).pack()
        self.e = tkinter.Entry(self.top)
        self.e.pack(padx=5)
        tkinter.Button(self.top, text="OK", command=self.ok).pack(pady=5)

    def ok(self):
        self.top.destroy()
        return self.e.get()


root = tkinter.Tk()
userName = MyDialog('Enter your name')
tkinter.Label(root, text="Hello {}".format(userName)).pack()

root.mainloop()

该对话框不仅应禁用主 window,而且应阻止调用它的任何代码。并且它应该能够将值传递回调用代码。

解决方案需要两个关键部分。首先,使用 grab_set 阻止另一个 window 中的所有事件(或者更准确地说,将所有事件发送到对话框 window)。其次,使用 wait_window 来防止该方法在对话框被销毁之前返回。

也就是说,您不应该像您的示例中那样使用它。在创建 window 之前,您需要有 mainloop 运行。它可能在某些平台上工作正常,但一般来说,在 mainloop 为 运行.

之前,您不应该期望您的 GUI 能够正常运行

这是一个简单的例子:

import Tkinter as tk

class MyDialog(object):
    def __init__(self, parent, prompt):
        self.toplevel = tk.Toplevel(parent)
        self.var = tk.StringVar()
        label = tk.Label(self.toplevel, text=prompt)
        entry = tk.Entry(self.toplevel, width=40, textvariable=self.var)
        button = tk.Button(self.toplevel, text="OK", command=self.toplevel.destroy)

        label.pack(side="top", fill="x")
        entry.pack(side="top", fill="x")
        button.pack(side="bottom", anchor="e", padx=4, pady=4)

    def show(self):
        self.toplevel.grab_set()
        self.toplevel.wait_window()
        value = self.var.get()
        return value

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.button = tk.Button(self, text="Click me!", command=self.on_click)
        self.label = tk.Label(self, text="", width=40)
        self.label.pack(side="top", fill="x")
        self.button.pack(padx=20, pady=20)

    def on_click(self):
        result = MyDialog(self, "Enter your name:").show()
        self.label.configure(text="your result: '%s'" % result)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()