如何使用tkinter在每个循环中重复获取Text小部件的内容?

时间:2017-10-20 11:08:54

标签: python text tkinter widget

我想反复获取Text小部件的内容,因此我可以分析它并获取有关输入内容的统计信息。这些统计数据需要在用户输入时实时更新,因此我需要变量currentContent来更新每个循环。我想做的就是这样。

main = tk.Tk()
# Y'know, all the typical window setup stuff.

currentContent = inputBox.get(0.0,END)
textBlobContent = TextBlob(currentContent)
# Basically here I'd do a bunch of stuff using TextBlob.

main.mainloop()

然而,这不起作用。只要窗口加载,它就会获取一次内容,然后停止。当然mainloop反复运行,它应该继续获取Text小部件的内容吗?

1 个答案:

答案 0 :(得分:5)

大部分时间都可以使用的简单解决方案是对<KeyRelease>进行绑定。这样就可以在用户输入时调用函数。每当用鼠标粘贴数据或通过其他方式(例如工具栏按钮)插入数据时,都不会触发回调。

更强大的解决方案是为窗口小部件设置代理,以便在窗口小部件中插入或删除任何内容时生成事件。此代理可以查看窗口小部件正在执行的操作(插入,删除,更改选择等)并生成事件。然后,您可以绑定到此事件以执行任何操作。

以下是自定义文本类的示例,只要插入或删除数据,就会生成<<TextModified>>事件:

import tkinter as tk

class CustomText(tk.Text):
    def __init__(self, *args, **kwargs):
        """A text widget that report on internal widget commands"""
        tk.Text.__init__(self, *args, **kwargs)

        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, command, *args):
        cmd = (self._orig, command) + args
        result = self.tk.call(cmd)

        if command in ("insert", "delete", "replace"):
            self.event_generate("<<TextModified>>")

        return result

这个代理做了四件事:

  1. 首先,它调用实际的widget命令,传入它收到的所有参数。
  2. 接下来,它会为每个插入和每次删除生成一个事件
  3. 然后它会生成虚拟事件
  4. 最后它返回实际小部件命令的结果
  5. 您可以像使用任何其他文本小部件一样使用此小部件,还可以将其绑定到<<TextModified>>

    例如,如果要在文本小部件中显示字符数,可以执行以下操作:

    import tkinter as tk
    
    # ... import of definition of CustomText goes here ...
    
    root = tk.Tk()
    label = tk.Label(root, anchor="w")
    text = CustomText(root, width=40, height=4)
    
    label.pack(side="bottom", fill="x")
    text.pack(side="top", fill="both", expand=True)
    
    def onModification(event):
        chars = len(event.widget.get("1.0", "end-1c"))
        label.configure(text="%s chars" % chars)
    
    text.bind("<<TextModified>>", onModification)
    
    root.mainloop()