tkinter text widget word wrap position - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: tkinter text widget word wrap position (/thread-32923.html) |
tkinter text widget word wrap position - chrisdb - Mar-17-2021 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 RE: tkinter text widget word wrap position - Larz60+ - Mar-17-2021 The text window described here has an expandable geometry, so the wrap position varies as the window is expanded and/or contracted. There are some command attributes that have some control over padding (spacing1, spacing2 and spacing3), as well as some modifiers in the wrap command: Quote:wrap If you don't already have a copy, I recommend downloading John Shipman's tkinter manual here: https://reu.cct.lsu.edu/documents/Python_Course/tkinter.pdf There are other commands that may help, starting on page 82 RE: tkinter text widget word wrap position - chrisdb - Mar-17-2021 (Mar-17-2021, 10:15 AM)Larz60+ Wrote: The text window described here has an expandable geometry, so the wrap position varies as the window is expanded and/or contracted. I've tried several methods, like 'dlineinfo' and 'bbox', but none of them provide me with the necessary info... RE: tkinter text widget word wrap position - deanhystad - Mar-17-2021 I think dlineinfo provides what ypu need, the vertical position of each line, but you need to use place instead of grid to position the line numbers. Even without word wrap this would be necessary to support rich text. RE: tkinter text widget word wrap position - chrisdb - Mar-18-2021 (Mar-17-2021, 08:45 PM)deanhystad Wrote: I think dlineinfo provides what ypu need, the vertical position of each line, but you need to use place instead of grid to position the line numbers. Even without word wrap this would be necessary to support rich text. Thx, I was looking at the wrong attribute of dlineinfo. A question though, what makes 'place' exactly better than 'grid' for the line numbers in this case? RE: tkinter text widget word wrap position - deanhystad - Mar-18-2021 Grid does not let you specify location, only relative location. Line number 11 might be 13 or 26 pixels below line number 10 depending on if line 10 wraps. I suppose you could add an empty label to the line number grid, but you'd have to keep track of that somehow. RE: tkinter text widget word wrap position - chrisdb - Mar-18-2021 Ok, but I'm using a text widget in which I display the line numbers. So that's probably my problem... Thanks! |