Is there a way to make the Tkinter text widget read only?

130,294

Solution 1

You have to change the state of the Text widget from NORMAL to DISABLED after entering text.insert() or text.bind() :

text.config(state=DISABLED)

Solution 2

text = Text(app, state='disabled', width=44, height=5)

Before and after inserting, change the state, otherwise it won't update

text.configure(state='normal')
text.insert('end', 'Some Text')
text.configure(state='disabled')

Solution 3

Very easy solution is just to bind any key press to a function that returns "break" like so:

import Tkinter

root = Tkinter.Tk() 

readonly = Tkinter.Text(root)
readonly.bind("<Key>", lambda e: "break")

Solution 4

The tcl wiki describes this problem in detail, and lists three possible solutions:

  1. The Disable/Enable trick described in other answers
  2. Replace the bindings for the insert/delete events
  3. Same as (2), but wrap it up in a separate widget.

(2) or (3) would be preferable, however, the solution isn't obvious. However, a worked solution is available on the unpythonic wiki:

 from Tkinter import Text
 from idlelib.WidgetRedirector import WidgetRedirector

 class ReadOnlyText(Text):
     def __init__(self, *args, **kwargs):
         Text.__init__(self, *args, **kwargs)
         self.redirector = WidgetRedirector(self)
         self.insert = self.redirector.register("insert", lambda *args, **kw: "break")
         self.delete = self.redirector.register("delete", lambda *args, **kw: "break")

Solution 5

If your use case is really simple, nbro's text.bind('<1>', lambda event: text.focus_set()) code solves the interactivity problem that Craig McQueen sees on OS X but that others don't see on Windows and Linux.

On the other hand, if your readonly data has any contextual structure, at some point you'll probably end up using Tkinter.Text.insert(position, text, taglist) to add it to your readonly Text box window under a tag. You'll do this because you want parts of the data to stand out based on context. Text that's been marked up with tags can be emphasized by calling .Text.tag_config() to change the font or colors, etc. Similarly, text that's been marked up with tags can have interactive bindings attached using .Text.tag_bind(). There's a good example of using these functions here. If a mark_for_paste() function is nice, a mark_for_paste() function that understands the context of your data is probably nicer.

Share:
130,294

Related videos on Youtube

rectangletangle
Author by

rectangletangle

Updated on March 27, 2022

Comments

  • rectangletangle
    rectangletangle about 2 years

    It doesn't look like it has that attribute, but it'd be really useful to me.

    • Exectron
      Exectron about 11 years
      A Tkinter Entry widget allows entry.config(state='readonly'). Unfortunately this doesn't seem to work for the Text widget.
  • Exectron
    Exectron about 11 years
    Then you can't select text, and copy it.
  • Exectron
    Exectron about 11 years
    What is idlelib and where does it come from? It would be good to have a solution that doesn't need an idlelib dependency.
  • Exectron
    Exectron about 11 years
    Then you can't select text, and copy it.
  • Exectron
    Exectron about 11 years
    On Ubuntu Linux, I can get idlelib by sudo apt-get install idle-python2.7
  • freakboy3742
    freakboy3742 almost 11 years
    idlelib is part of the Python standard library. However, for some reason Ubuntu seems to enjoy packaging Python in lots of little parts.
  • Dologan
    Dologan about 10 years
    Selecting and copying (through CTRL-C in Windows and automatically in Linux) seem to work just fine for me.
  • manty
    manty over 9 years
    You can select text and copy also. It's working for me in windows
  • nbro
    nbro over 8 years
    @CraigMcQueen You can actually do it by binding the <1> with a function that sets the focus on the text widget: text.bind("<1>", lambda event: text.focus_set()).
  • Colby Gallup
    Colby Gallup over 8 years
    @CraigMcQueen - I'm pretty sure that this is handled internally regardless of the state. I don't know if you can disable selecting and copying, either.
  • Russell Smith
    Russell Smith over 4 years
    You lose a lot of functionality when you do that.
  • Gary02127
    Gary02127 over 3 years
    As a side note, disabling the left mouse button precludes one from clicking on and selecting the Text widget, which does most of the job. But disabling keys helps, too, in case the Text widget can be tabbed into or is given keyboard focus.
  • Mikeologist
    Mikeologist almost 3 years
    @BryanOakley What functionality would you still need if it's intended to be used as read-only?
  • Russell Smith
    Russell Smith almost 3 years
    the ability to scroll and the ability to apply formatting to individual characters are the two biggest things you lose. Plus, you lose the ability to select text, and word wrapping in the text widget is much better than in a label.