Readonly tkinter text widget

python, text, tkinter

Solution

The reason that the last character is inserted is because the default bindings (which causes the insert) happens after custom bindings you put on the widget. So your bindings fire first and then the default binding inserts the characters. There are other questions and answers here that discuss this in more depth. For example, see https://stackoverflow.com/a/11542200/

However, there is a better way to accomplish what you are trying to do. If you want to create a readonly text widget, you can set the `state` attribute to `"disabled"`. This will prevent all inserts and deletes (and means you need to revert the state whenever you want to programmatically enter data).

On some platforms it will seem like you can't highlight and copy text, but that is only because the widget won't by default get focus on a mouse click. By adding a binding to set the focus, the user can highlight and copy text but they won't be able to cut or insert.

Here's an example using python 2.x; for 3.x you just have to change the imports:

import Tkinter as tk
from ScrolledText import ScrolledText

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        t = ScrolledText(self, wrap="word")
        t.insert("end", "Hello\nworld")
        t.configure(state="disabled")
        t.pack(side="top", fill="both", expand=True)

        # make sure the widget gets focus when clicked
        # on, to enable highlighting and copying to the
        # clipboard.
        t.bind("<1>", lambda event: t.focus_set())

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

Problem

I want to use `tkinter text widget` as a `readonly` widget. It should act as a `transcript` area. My idea is to keep this transcript in a `file` and whenever the user writes anything, just remove all the contents of the widget, and rewrite it again. The code will look like: ``` transcript_entry = SimpleEditor() # SimpleEditor is inherited from ScrolledText transcript_entry.text.delete("1.0", END) # this is just a test string, it should be the contents of the transcript file transcript_entry.text.insert("1.0", "This is test transcript") transcript_entry.text.bind("<KeyPress>", transcript_entry.readonly) ``` And `readonly` function will look like: ``` def readonly(self, event): self.text.delete("1.0", END) # this is just a test string, it should be the contents of the transcript file self.text.insert("1.0", "This is test transcript") ``` The bug here is that the last character entered by the user is added to the transcript. I suspect the reason is that the readonly function is called, `then` the user input is wrote to the widget. How to reverse this order & let the readonly function be called `after` the user input is wrote to the widget? Any hints?

Original source

Related problems