如何使用 tkinter 在每个循环中重复获取文本小部件的内容?
How to repeatedly get the contents of a Text widget every loop with tkinter?
我想重复获取文本小部件的内容,以便对其进行分析并获取有关已输入内容的统计信息。这些统计数据需要在用户键入时实时更新,因此我需要变量 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()
但是,这不起作用。一旦 window 加载,它就获取一次内容,然后停止。 mainloop 肯定是反复运行,它应该一直获取 Text widget 的内容吧?
一个在大多数情况下都有效的简单解决方案是对 <KeyRelease>
进行绑定。这将使一个函数在用户输入时被调用。这不会在使用鼠标粘贴数据或通过其他方式(例如工具栏按钮)插入数据时触发回调。
一个更强大的解决方案是为小部件设置代理,以便在小部件中插入或删除任何内容时生成一个事件。该代理可以查看小部件正在执行的操作(插入、删除、更改选择等)并生成事件。然后你可以绑定到这个事件来做任何你想做的事。
下面是自定义文本 class 的示例,每当插入或删除数据时都会生成 <<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
这个代理做四件事:
- 首先,它调用实际的小部件命令,传入它收到的所有参数。
- 接下来它为每次插入和删除生成一个事件
- 然后它会生成一个虚拟事件
- 最后 returns 实际小部件命令的结果
您可以像使用任何其他文本小部件一样使用此小部件,此外还可以绑定到 <<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()
我想重复获取文本小部件的内容,以便对其进行分析并获取有关已输入内容的统计信息。这些统计数据需要在用户键入时实时更新,因此我需要变量 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()
但是,这不起作用。一旦 window 加载,它就获取一次内容,然后停止。 mainloop 肯定是反复运行,它应该一直获取 Text widget 的内容吧?
一个在大多数情况下都有效的简单解决方案是对 <KeyRelease>
进行绑定。这将使一个函数在用户输入时被调用。这不会在使用鼠标粘贴数据或通过其他方式(例如工具栏按钮)插入数据时触发回调。
一个更强大的解决方案是为小部件设置代理,以便在小部件中插入或删除任何内容时生成一个事件。该代理可以查看小部件正在执行的操作(插入、删除、更改选择等)并生成事件。然后你可以绑定到这个事件来做任何你想做的事。
下面是自定义文本 class 的示例,每当插入或删除数据时都会生成 <<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
这个代理做四件事:
- 首先,它调用实际的小部件命令,传入它收到的所有参数。
- 接下来它为每次插入和删除生成一个事件
- 然后它会生成一个虚拟事件
- 最后 returns 实际小部件命令的结果
您可以像使用任何其他文本小部件一样使用此小部件,此外还可以绑定到 <<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()