Mar-17-2021, 07:42 AM
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.
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