How to enter text into two text widgets by just entring into same widget How to enter text into two text widgets by just entring into same widget tkinter tkinter

How to enter text into two text widgets by just entring into same widget


If you want the contents of the two text widgets to be identical, the text widget has a little-used feature known as peer widgets. In effect, you can have multiple text widgets that share the same underlying data structure.

The canonical tcl/tk documentation describes peers like this:

The text widget has a separate store of all its data concerning each line's textual contents, marks, tags, images and windows, and the undo stack.

While this data store cannot be accessed directly (i.e. without a text widget as an intermediary), multiple text widgets can be created, each of which present different views on the same underlying data. Such text widgets are known as peer text widgets.

Unfortunately, tkinter's support of text widget peering is not complete. However, it's possible to create a new widget class that makes use of the peering function.

The following defines a new widget, TextPeer. It takes another text widget as its master and creates a peer:

import tkinter as tkclass TextPeer(tk.Text):    """A peer of an existing text widget"""    count = 0    def __init__(self, master, cnf={}, **kw):        TextPeer.count += 1        parent = master.master        peerName = "peer-{}".format(TextPeer.count)        if str(parent) == ".":            peerPath = ".{}".format(peerName)        else:            peerPath = "{}.{}".format(parent, peerName)        # Create the peer        master.tk.call(master, 'peer', 'create', peerPath, *self._options(cnf, kw))        # Create the tkinter widget based on the peer        # We can't call tk.Text.__init__ because it will try to        # create a new text widget. Instead, we want to use        # the peer widget that has already been created.        tk.BaseWidget._setup(self, parent, {'name': peerName})

You use this similar to how you use a Text widget. You can configure the peer just like a regular text widget, but the data will be shared (ie: you can have different sizes, colors, etc for each peer)

Here's an example that creates three peers. Notice how typing in any one of the widgets will update the others immediately. Although these widgets share the same data, each can have their own cursor location and selected text.

import tkinter as tkroot = tk.Tk()text1 = tk.Text(root, width=40, height=4, font=("Helvetica", 20))text2 = TextPeer(text1, width=40, height=4, background="pink", font=("Helvetica", 16))text3 = TextPeer(text1, width=40, height=8, background="yellow", font=("Fixed", 12))text1.pack(side="top", fill="both", expand=True)text2.pack(side="top", fill="both", expand=True)text3.pack(side="top", fill="both", expand=True)text2.insert("end", (    "Type in one, and the change will "    "appear in the other."))root.mainloop()


The quickest way to update text in a 2nd box that I have found is to use replace() and get(). That said after testing your example I am not really seeing a noticeable delay.

We can use the Modified event to manage our updates and after each modification we can tell text1 that Modified is False so we get an update on every change.

Let me know if this was what you were looking for.

Try this:

import tkinter as tkdef update_text2(_=None):    text2.replace('1.0', 'end', text1.get('1.0', 'end'))    text1.edit_modified(False)root = tk.Tk()text1 = tk.Text(root)text2 = tk.Text(root)text1.pack()text2.pack()text1.bind('<<Modified>>', update_text2)root.mainloop()