簡體   English   中英

每次在文本框中輸入文本時,如何使用 tkinter 更新 label

[英]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.inserttext_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM