问题描述
import tkinter as tk
def on_modify(event):
chars = event.widget.get('0.0', 'end')
label.configure(text='%s chars' % len(chars))
print(chars)
win = tk.Tk()
label = tk.Label(win, anchor=tk.W)
label.pack(side=tk.BOTTOM, fill=tk.X)
text = tk.Text(win, height=4)
text.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
text.focus()
text.bind('<Key>', on_modify)
win.mainloop()
对 tk.Text
类直接绑定 <Key>
事件,获取的内容不实时且不准确,特别在发生粘贴和退格的时候
解决方案
修改 get()
方法并实现自定义多行文本框类
import tkinter as tk
class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
"""自定义多行文本框类,可实时监控变化事件"""
tk.Text.__init__(self, *args, **kwargs)
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):
if command == 'get' and (args[0] == 'sel.first' and args[1] == 'sel.last') and not self.tag_ranges('sel'):
return
if command == 'delete' and (args[0] == 'sel.first' and args[1] == 'sel.last') and not self.tag_ranges('sel'):
return
cmd = (self._orig, command) + args
result = self.tk.call(cmd)
if command in ('insert', 'delete', 'replace'):
self.event_generate('<<TextModified>>')
return result
def on_modify(event):
chars = event.widget.get('1.0', 'end-1c')
label.configure(text='%s chars' % len(chars))
print(chars)
win = tk.Tk()
label = tk.Label(win, anchor=tk.W)
label.pack(side=tk.BOTTOM, fill=tk.X)
text = CustomText(win, height=4)
text.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
text.focus()
text.bind('<<TextModified>>', on_modify)
win.mainloop()
效果
或调用 idlelib.redirector.WidgetRedirector
(本人调试失败,有成功的朋友请不吝赐教)
import tkinter as tk
from idlelib.redirector import WidgetRedirector
def on_insert(*args):
chars = text.get('0.0', 'end')
label.configure(text='%s chars' % len(chars))
print(args)
old_insert(*args)
def on_delete(*args):
chars = text.get('0.0', 'end')
label.configure(text='%s chars' % len(chars))
print(args)
old_delete(*args)
win = tk.Tk()
label = tk.Label(win, anchor=tk.W)
label.pack(side=tk.BOTTOM, fill=tk.X)
text = tk.Text(win, height=4)
text.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
text.focus()
redirector = WidgetRedirector(text)
old_insert = redirector.register('insert', on_insert)
old_delete = redirector.register('delete', on_delete)
win.mainloop()