阻止输入对话框

时间:2015-11-08 15:49:05

标签: python tkinter dialog modal-dialog user-input

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

我需要用户在代码可以继续之前输入一个值。

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

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()

对话框不仅要禁用主窗口,还要阻止任何调用它的代码。它应该能够将值传递回调用代码。

1 个答案:

答案 0 :(得分:1)

解决方案需要两个关键部分。首先,使用grab_set来阻止其他窗口中的所有事件(或者更准确地说,将所有事件发送到对话框窗口)。其次,使用wait_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()