我正在尝试将一个大型文本输入弹出窗口作为gui的一部分。这个想法是让段落长的用户输入。问题是方法get_big_text()
在按下按钮之前返回。如何像这样弹出一个单独的窗口,并能够将用户的文本保存到我的控制程序中的变量中?我的程序中的其他所有内容一直在运行,直到我尝试实现它。我是gui编程的新手。我觉得在这里等待用户输入有一些根本不同的东西,但我不能在功能上下文中把它包围起来。
我的目标是让行print(foo.get_big_text())
打印用户的文字,但当然会打印None
,因为get_big_text()
方法已完成。
我遗漏了gui其余部分的细节,写了__init__()
,可能不需要在那里,但这是我的gui如何出现的基础知识。 Toplevel
窗口小部件是我gui中唯一没有以某种方式连接到root
的窗口小部件。
from tkinter import *
class Gui:
def __init__(self, root):
tframe = Frame(root)
tframe.pack(side='top')
bframe = Frame(root)
bframe.pack(side='bottom')
self.txt = Text(tframe)
self.txt.insert('0.0', 'Totally foobar')
self.txt.pack()
self.btn = Button(bframe, text='OK')
self.btn.pack()
def get_big_text(self, title='', text=''):
popup = Toplevel(height=160, width=180)
popup.title(title)
txtframe = Frame(popup)
txtframe.pack()
big_text = Text(txtframe)
big_text.insert('0.0',text)
big_text.pack()
btnframe = Frame(popup)
btnframe.pack()
grab_text = Button(btnframe)
grab_text.config(text="Done", command=lambda: big_text.get('0.0', 'end'))
grab_text.pack()
root=Tk()
root.title('Example')
foo = Gui(root)
print(foo.get_big_text())
root.mainloop()
答案 0 :(得分:1)
您应该将文本传递给班级中的一个函数,然后随意执行任何操作(如打印):
from Tkinter import *
class Gui:
def __init__(self, root):
tframe = Frame(root)
tframe.pack(side='top')
bframe = Frame(root)
bframe.pack(side='bottom')
self.txt = Text(tframe)
self.txt.insert('0.0', 'Totally foobar')
self.txt.pack()
self.btn = Button(bframe, text='OK')
self.btn.pack()
def f(self, text):
print(text)
def get_big_text(self, title='', text=''):
popup = Toplevel(height=160, width=180)
popup.title(title)
txtframe = Frame(popup)
txtframe.pack()
big_text = Text(txtframe)
big_text.insert('0.0',text)
big_text.pack()
btnframe = Frame(popup)
btnframe.pack()
grab_text = Button(btnframe)
grab_text.config(text="Done", command=lambda: self.f(big_text.get('0.0', 'end')))
grab_text.pack()
root=Tk()
root.title('Example')
foo = Gui(root)
foo.get_big_text()
root.mainloop()
如果你想在之后打印文字,你可以进行修改:
在Gui.f
上:
def f(self, text):
self.text = text
在代码的最后:
root.mainloop()
print(foo.text)
答案 1 :(得分:1)
经过@xndrme的一些建议,以及一些艰难的思考,我意识到解决方案非常简单。只是我不习惯这种功能风格的编程。但是,发现这个真的很有趣。
我希望get_big_text()
方法返回文本,以便我可以将其传递到其他地方,并在文本到来时“用它做”。解决方案是将匿名函数传递给方法并“告诉它”当它到来时应该用它做什么。
请注意callback
get_big_text()
参数
from tkinter import *
class Gui:
def __init__(self, root):
tframe = Frame(root)
tframe.pack(side='top')
bframe = Frame(root)
bframe.pack(side='bottom')
self.txt = Text(tframe)
self.txt.insert('0.0', 'Totally foobar')
self.txt.pack()
self.btn = Button(bframe, text='OK')
self.btn.pack()
def get_big_text(self, callback, title='', text=''):
popup = Toplevel(height=160, width=180)
popup.title(title)
txtframe = Frame(popup)
txtframe.pack()
big_text = Text(txtframe)
big_text.insert('0.0',text)
big_text.pack()
btnframe = Frame(popup)
btnframe.pack()
grab_text = Button(btnframe)
grab_text.config(text="Done", command=lambda:callback(big_text.get('0.0', 'end')))
grab_text.pack()
root=Tk()
root.title('Example')
foo = Gui(root)
foo.get_big_text(lambda x:print(x))
root.mainloop()
答案 2 :(得分:1)
对话框的一般流程是创建窗口,然后调用wait_window
等待窗口被用户解除。然后你的功能可以返回你想要的任何东西
有一些鸡与蛋的事情正在发生,因为你需要在对话框被销毁之前从对话框中获取值,因为文本小部件将在顶层时被销毁被毁了。您可以通过显式管理窗口的销毁来执行此操作(读取:在实际销毁窗口之前获取值)。
这是一个工作示例,尝试尽可能多地保留代码,但不使用全局导入:
import Tkinter as tk
class CustomDialog(object):
def __init__(self, parent, title="Enter a paragraph", default_text=""):
self.parent = parent
self.title = title
self.default = default_text
def show(self):
self.popup = tk.Toplevel(self.parent)
self.popup.title(self.title)
txtframe = tk.Frame(self.popup)
txtframe.pack()
self.big_text = tk.Text(txtframe)
self.big_text.insert('1.0',self.default)
self.big_text.pack()
btnframe = tk.Frame(self.popup)
btnframe.pack()
grab_text = tk.Button(btnframe)
grab_text.config(text="Done", command=self.done)
grab_text.pack()
# make sure our "done" method gets called even if the
# user destroys the window
self.popup.wm_protocol("WM_DELETE_WINDOW", self.done)
# wait for the window to be destroyed
root.wait_window(self.popup)
return self.data
def done(self, *args):
# get the data from the window, then destroy
# the window and return to the caller
self.data = self.big_text.get("1.0", "end-1c")
self.popup.destroy()
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
b = tk.Button(self, text="Get Input", command=self.go)
b.pack()
def go(self):
dialog = CustomDialog(self, default_text="totally foobar")
result = dialog.show()
print "result:", result
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
您拥有的另一个选项是将回调传递给对话框,并将该回调绑定到“完成”按钮。这样,无论何时用户单击该按钮,您都可以在销毁窗口之前执行回调以对数据执行任何操作。
这就是你实现非模态对话框的方法,因为你不一定要破坏窗口。字体对话框就是一个很好的例子,您可能希望将对话框保持打开状态一段时间,并影响当前选择的内容。
effbot网站在对话框上有一个不错的写作。见http://effbot.org/tkinterbook/tkinter-dialog-windows.htm