[英]How do you update a label every time text is typed into a textbox, using tkinter
我正在尝试创建一个应用程序,其中一部分涉及 label ,它会在每次更新时动态更改并显示在文本框中键入的字符数。 我找不到有关此的任何信息,并且不确定这是否可能。
在文本小部件更改时获得通知的最简单方法是拦截低级插入、删除和替换命令。 当它们发生时,可以生成一个事件,然后您可以绑定到该事件。
这涉及到一点点 tcl voodoo,但无论您在小部件中键入、使用鼠标粘贴还是直接调用 insert 或 delete 方法,它都可以正常工作。
这是一个完整的例子:
import tkinter as tk
class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
"""A text widget that supports a <<TextChanged>> event"""
tk.Text.__init__(self, *args, **kwargs)
self.tk.eval('''
proc widget_proxy {widget widget_command args} {
# call the real tk widget command with the real args
set result [uplevel [linsert $args 0 $widget_command]]
# if the contents changed, generate an event we can bind to
if {([lindex $args 0] in {insert replace delete})} {
event generate $widget <<TextModified>> -when tail
}
# return the result from the real widget command
return $result
}
''')
# this replaces the underlying widget with the proxy
self.tk.eval('''
rename {widget} _{widget}
interp alias {{}} ::{widget} {{}} widget_proxy {widget} _{widget}
'''.format(widget=str(self)))
def update_char_count(event):
count = event.widget.count("1.0", "end-1c")
# count is a tuple; the character count is the first element
count = 0 if not count else count[0]
label.configure(text=f"Characters: {count}")
root = tk.Tk()
text = CustomText(root)
label = tk.Label(root, anchor="w")
label.pack(side="bottom", fill="x")
text.pack(fill="both", expand=True)
text.bind("<<TextModified>>", update_char_count)
root.mainloop()
如果您想要一个更简单的解决方案,需要调用者进行更多工作,请查看以下内容:
import tkinter as tk
def callback(event):
# After 1 ms call `_callback`
# That is to make sure that tkinter has handled the keyboard press
root.after(1, _callback)
def _callback():
# The `-1` is there because when you have `text_widget.get(..., "end")`
# It adds a "\n" character at then end
number_of_chars = len(text_widget.get("1.0", "end")) - 1
print(number_of_chars)
root = tk.Tk()
text_widget = tk.Text(root)
text_widget.pack()
text_widget.bind("<Key>", callback)
root.mainloop()
这基本上将所有键盘按下绑定到callback
function。 我想不出任何方法可以在不按键盘按钮的情况下更改文本小部件中的文本。
请注意,它只会在按下某个键时运行,因此如果您调用text_widget.insert
或text_widget.delete
(@acw1668 发现该问题),它将无法工作。 在调用.insert
/ .delete
之后调用_callback
是调用者的责任。
一个更简单的答案是始终使用某人已经创建的内容:D
# `idlelib` is part of the standard library
from idlelib.redirector import WidgetRedirector
import tkinter as tk
def my_insert(*args):
original_insert(*args)
update_label()
def my_delete(*args):
original_delete(*args)
update_label()
def my_replace(*args):
original_replace(*args)
update_label()
def update_label():
number_of_chars = len(text.get("1.0", "end")) - 1
print(number_of_chars)
root = tk.Tk()
text = tk.Text(root)
text.pack()
redir = WidgetRedirector(text)
original_insert = redir.register("insert", my_insert)
original_delete = redir.register("delete", my_delete)
original_replace = redir.register("replace", my_replace)
root.mainloop()
即使您使用text.insert(...)
,此解决方案也有效
有关其工作原理的更多信息,请使用help(WidgetRedirector)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.