Python Forum
tkinter text widget word wrap position
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tkinter text widget word wrap position
#1
Hi,

I'm trying to figure out the index position on where the tkinter text widget cuts of the word when using WORD wrap. I thought the newline '\n' would indicate this, but I was wrong. If you see the example below (I replaced '\n' with '$'), you see the cut off word is not indicated by a '\n'.

Is there any way I can detect the index of the cut off position? I would like to use this to create a text editor with line numbers when using WORD wrap.

from tkinter import *
from decimal import Decimal

class app:
    def __init__(self, master):
        self.master = master

        master.title("PyEditor")
        master.geometry("720x180")

        master.grid_columnconfigure(1, weight=1)
        master.grid_rowconfigure(0, weight=1)

        self.lineframe = LineNumberFrame(master)
        self.lineframe.grid(row=0, column=0)
        
        self.edit_space = CustomText(master, wrap= WORD)
        self.edit_space.grid(row=0, column=1, sticky=NSEW)
        self.lineframe.attach(self.edit_space)
        self.edit_space.bind("<<TextModified>>", self._on_change)
        
        self.edit_scroll = Scrollbar(master, orient = VERTICAL, command = self._multi_scroll )
        
        self.edit_scroll.grid(row = 0, column = 2, sticky=NS)
        
        
        self.edit_space.configure(yscrollcommand = self._scroll1)
        self.lineframe.line_numbers.configure(yscrollcommand = self._scroll2)
        
        master.bind_all("<MouseWheel>", self._on_mousewheel)
        
    def _scroll1(self, *args):
        if self.lineframe.line_numbers.yview() != self.edit_space.yview():
            self.lineframe.line_numbers.yview_moveto(args[0])
            
        self.edit_scroll.set(*args)
        
    def _scroll2(self, *args):
        if self.edit_space.yview() != self.lineframe.line_numbers.yview():
            self.edit_space.yview_moveto(args[0])
            
        self.edit_scroll.set(*args)
        
    def _on_change(self, event):
        self.lineframe.redraw()
        
    def _multi_scroll(self, *args):
        self.edit_space.yview(*args)
        self.lineframe.line_numbers.yview(*args)
        
    
        
    def _on_mousewheel(self,event):
        self.edit_space.yview("scroll", -1 * (event.delta), "units")
        self.lineframe.line_numbers.yview("scroll", -1 * (event.delta), "units")

class LineNumberFrame(Frame):    
    def __init__(self, master: Tk = None):
        super().__init__(master, width = 1)
        self.master = master
        self.grid(row = 0, column = 0, sticky="nsew")
        self.create_widgets()
        
    def create_widgets(self):
        self.line_numbers = Text(self.master, width = 3)
        self.line_numbers.config(state = DISABLED)
        self.line_numbers.grid(row=0, column=0, sticky=NSEW)
        
    def attach(self, text_widget):
        self.text_widget = text_widget
        
    def redraw(self):
        self.line_numbers.config(state = NORMAL)
        self.line_numbers.delete("1.0", END)
        
                
        i = 1.0
        lastline = self.text_widget.index("end")
        
        is_first = True

        while True :
            if Decimal(i).compare(Decimal(lastline)) >= 0:
                break

            linenum = str(i).split(".")[0]          
            print("idx: " + self.text_widget.get(str(i) + " linestart", str(i) + " lineend+1c").replace("\n", "$"))

            if is_first == True:
                self.line_numbers.insert(END, linenum)
                is_first = False
            else:
                self.line_numbers.insert(END, "\n" + linenum)

            i = self.text_widget.index("%s+1line" % i)
            
        self.line_numbers.config(state = DISABLED)
        
        

class CustomText(Text):
    def __init__(self, *args, **kwargs):
        """A text widget that report on internal widget commands"""
        Text.__init__(self, *args, **kwargs)

        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)

    def _proxy(self, command, *args):
        cmd = (self._orig, command) + args
        result = self.tk.call(cmd)
        
       

        if command in ("insert", "delete", "replace"):
            self.event_generate("<<TextModified>>")

        return result
        
        

root = Tk()
my_gui = app(root)

# Insert some text
my_gui.edit_space.insert(END, "A very long line to see how the word wrap works. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\n")

for x in range(2,10):   
    my_gui.edit_space.insert(END, "Line " + str(x) +"\n")

root.mainloop()
Thanks
Reply


Messages In This Thread
tkinter text widget word wrap position - by chrisdb - Mar-17-2021, 07:42 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Problems trying to position images with Tkinter emont 3 792 Dec-12-2023, 07:20 AM
Last Post: menator01
  TKinter Widget Attribute and Method Quick Reference zunebuggy 3 866 Oct-15-2023, 05:49 PM
Last Post: zunebuggy
  [Tkinter] Updating tkinter text BliepMonster 5 6,084 Nov-28-2022, 01:42 AM
Last Post: deanhystad
  [Tkinter] The Text in the Label widget Tkinter cuts off the Long text in the view malmustafa 4 4,944 Jun-26-2022, 06:26 PM
Last Post: menator01
  Tkinter Exit Code based on Entry Widget Nu2Python 6 3,018 Oct-21-2021, 03:01 PM
Last Post: Nu2Python
  tkinter change the text of the checkbox zazas321 1 3,858 Sep-17-2021, 06:19 AM
Last Post: zazas321
  [Tkinter] Text widget inert mode on and off rfresh737 5 3,897 Apr-19-2021, 02:18 PM
Last Post: joe_momma
  Line numbers in Text widget rfresh737 3 5,438 Apr-15-2021, 12:30 PM
Last Post: rfresh737
  [Tkinter] tkinter.Menu – How to make text-variable? Sir 3 5,671 Mar-10-2021, 04:21 PM
Last Post: Sir
  tkinter python button position problem Nick_tkinter 3 3,582 Jan-31-2021, 05:15 AM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020