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.*
- 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.)
- Use create_text on a
Canvas
, which is scollable.
However, AFAIK, I cannot copy such text.
pack
Labels into aCanvas
, 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()