如何在标准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()
对话框不仅要禁用主窗口,还要阻止任何调用它的代码。它应该能够将值传递回调用代码。
答案 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()