Home > database >  Copyable scrolling text in tkinter
Copyable scrolling text in tkinter

Time:12-30

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]

CodePudding user response:

I found the answer! The workaround is stupid, but it works. Enter-- DOUBLE BUFFERING! Code says more than a thousand words:

class Drawing:
    def __init__(self,prnt,w=400,h=200):
        self.txts = []
        prntt = Frame(prnt,width=w,height=h)
        prntt.pack_propagate(False)
        self.frontbuf = Text(prntt,font="Courier 10",width=w,height=h,wrap="word")
        self.backbuf = Text(prntt,font="Courier 10",width=w,height=h,wrap="word")
        self.p = prntt
        self.w = w
        self.h = h
    def pack(self,*a,**k):
        self.p.pack(*a,**k)
    def set(self,tex):
        self.backbuf.config(state="normal")
        self.backbuf.delete("0.0",END)
        self.backbuf.insert(END,tex)
        H = self.backbuf.bbox(END "-1c")
        self.frontbuf.destroy()
        self.frontbuf = Text(self.p,font="Courier 10",width=self.w,height=self.h)
        self.backbuf.config(yscrollcommand=self.yscmd,state="disabled")
        self.backbuf.pack(side=TOP,expand=YES,fill=BOTH)
        self.frontbuf,self.backbuf = self.backbuf,self.frontbuf
    def yview(self,*a,**k):
        self.frontbuf.yview(*a,**k)
    def yscrollcmd(self,cmd):
        self.yscmd = cmd

CodePudding user response:

import tkinter as tk
from tkinter import scrolledtext

# Create the root window
root = tk.Tk()

# Create a ScrolledText widget with the specified text
text = scrolledtext.ScrolledText(root, wrap='word')
text.insert('1.0', """This is some immutable text that can be scrolled and copied
...
.
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
This is some immutable text that can be scrolled and copied""")

# Configure the widget to be non-editable
text.config(state='disabled')

# Pack the widget and start the event loop
text.pack()
root.mainloop()
  • Related