繁体   English   中英

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

[英]Tkinter Large Text Dialogue (save string on button click)

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

您应该将文本传递给类中的一个函数,然后随意执行任何操作(如打印):

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完成打印文本可以进行以下修改:

  1. Gui.f

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

     root.mainloop() print(foo.text) 

经过@xndrme的一些建议,以及一些艰难的思考,我意识到解决方案很简单。 只是我不习惯这种功能风格的编程。 但是,发现这个真的很有趣。

我希望get_big_text()方法返回文本,以便我可以将它传递到其他地方,并在文本到来时用它“做点什么”。 解决方案是将匿名函数传递给方法并“告诉它”当它到来时应该用它做什么。

注意get_big_text()的新callback参数

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

对话框的一般流程是创建窗口,然后调用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM