Tkinter大文本对话(点击按钮时保存字符串)

时间:2014-02-17 16:40:23

标签: python python-3.x tkinter

我正在尝试将一个大型文本输入弹出窗口作为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()

3 个答案:

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

如果你想在之后打印文字,你可以进行修改:

  1. Gui.f上:

        def f(self, text):
            self.text = text
    
  2. 在代码的最后:

    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