Python tkinter text modified callback

后端 未结 2 2011
野趣味
野趣味 2020-12-10 17:04

In python 2.7, I am trying to get a callback every time something is changed in the Tkinter Text widget.

The program uses multiple frames based on code found here:

2条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-10 17:54

    I suggest a simpler approach. You can set up a proxy for the widget, and within that proxy you can detect whenever anything was inserted or deleted. You can use that information to generate a virtual event, which can be bound to like any other event.

    Let's start by creating a custom text widget class, which you will use like any other text widget:

    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("<>")
    
            return result
    

    The proxy in this example does three things:

    1. First it calls the actual widget command, passing in all of the arguments it received.
    2. Next it generates an event for every insert and every delete
    3. Then it then generates a virtual event
    4. And finally it returns the results of the actual widget command

    You can use this widget exactly like any other Text widget, with the added benefit that you can bind to <>.

    For example, if you wanted to display the number of characters in the text widget you could do something like this:

    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("<>", onModification)
    
    root.mainloop()
    

提交回复
热议问题