Search code examples
pythonpython-3.xtkinterscrolltkinter-canvas

Copyable scrolling text in tkinter


I wanted to create a scrollable, copyable text in tkinter. This text should be immutable to the user, but I can change it.

Although this seems simple, there are some ways to approach it, but there are unsatisfactory things about each approach.*

  1. Use a state=disabled Text widget.

However, this also disallows my program to change it, which means I have to temporarily enable the widget, which can result it the user adding a character or two if they spam a key in the textbox.(Yes, it does matter, I want it to be absolutely immutable.)

  1. Use create_text on a Canvas, which is scollable.

However, AFAIK, I cannot copy such text.

  1. pack Labels into a Canvas, which is scrollable.

However, AFAIK, They don't scroll with the canvas.

One thing that could possible work is Canvas.create_window, but I can't even find a document of it, and the help text says nothing useful.

help> tkinter.Canvas.create_window
Help on function create_window in tkinter.Canvas:

tkinter.Canvas.create_window = create_window(self, *args, **kw)
    Create window with coordinates x1,y1,x2,y2.

help> 

[sic]


Solution

  • What about this approach?:

    from tkinter.scrolledtext import ScrolledText
    import tkinter as tk
    
    def return_break(event:tk.Event) -> str:
        return "break"
    
    
    root = tk.Tk()
    text = ScrolledText(root)
    text.pack()
    text.bind("<KeyPress>", return_break)
    text.insert("end", "Hello"+"\n"*40+"World.")
    
    root.mainloop()
    

    You return "break" from the events that you don't want tkinter to handle like "<KeyPress>". For this approach to work, when inserting new text, don't use .insert("insert", ...) as the user can change that, user .insert("end", ...) instead.