【问题标题】:Blocking Input Dialog Box阻止输入对话框
【发布时间】:2016-02-09 07:29:02
【问题描述】:

如何在标准 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()

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

【问题讨论】:

  • @StevenSummers 该解决方案不提供代码阻塞。
  • 您能否澄清一下哪些代码会被阻止,哪些值会被传回?比如,如果一个按钮打开了MyDialog然后阻止按钮再次打开?
  • 在用户关闭对话框之前,不应执行行 tkinter.Label(root...,此时您将在 userName 中获得用户提供的值。
  • 你不能在按钮点击事件中创建它吗?把它放在活动之外似乎很奇怪。

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


【解决方案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()

【讨论】:

  • 优秀。我只希望这已经是tkinter 的一部分,有点像tkinter.messagebox。但这样一来,它的可定制性就更高了。
  • @coding4fun:这种类型的对话框是 tkinter 的一部分。它叫askstring
猜你喜欢
  • 2019-06-21
  • 1970-01-01
  • 2016-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多