Python Forum
[Tkinter] How to get the accurate end of the tex widget for highligtng
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] How to get the accurate end of the tex widget for highligtng
#1
Hello, I have been struggling with this problem for some time now. The code below is supposed to highlight text added to the text widget if the "bg_color" parameter is not None. No coloring appears, but if additional lines are added afterward, color may fill the remainder of the last line. I have determined that this occurs because the self.text_area.index(tk.END) erroneously displays the end of the text as being at the beginning of the next line, even if there is no next line. How do I modify this function to highlight the text correctly?
Wall
    def update_text(self, text, clear_first, bg_color=None):
        if clear_first:
            self.text_area.delete(1.0, tk.END)  # Clear the text area

        # Capture the starting index
        start_index = self.text_area.index(tk.END)
        print(self.text_area.index(tk.END))

        # Insert the new text
        self.text_area.insert(tk.END, text)

        # Capture the ending index
        end_index = self.text_area.index(tk.END)
        print(self.text_area.index(tk.END))

        if bg_color:
            # Apply a tag with the background color
            tag_name = f"bg_color_{randint(1, 10000)}"  # Create a unique tag name
            self.text_area.tag_add(tag_name, start_index, end_index)
            self.text_area.tag_config(tag_name, background=bg_color)
Reply
#2
Text always contains a newline at the end. "end" is the position of this newline. To get the position before the newline use "end -1c".
import tkinter as tk


class Window(tk.Tk):
    def __init__(self):
        super().__init__()
        self.text_tag = 0
        self.text_area = tk.Text(self, wrap="word")
        self.text_area.pack(expand=True, fill=tk.BOTH)

    def update_text(self, text, clear_first=False, bg_color=None):
        if clear_first:
            self.text_area.delete(1.0, tk.END)
        start_index = self.text_area.index("end - 1c")
        self.text_area.insert(tk.END, text)
        if bg_color:
            tag_name = f"bg_color_{self.text_tag}"
            end_index = self.text_area.index("end - 1c")
            print(start_index, end_index, bg_color, tag_name)
            self.text_tag += 1
            self.text_area.tag_add(tag_name, start_index, end_index)
            self.text_area.tag_config(tag_name, background=bg_color)


window = Window()
window.update_text("This is regular text.")
window.update_text(" This is red text.", bg_color="pink")
window.update_text(" This is blue text.", bg_color="lightblue")
window.update_text(" This is yellow text.", bg_color="yellow")
window.update_text(" Back to normal text.")

window.mainloop()
You can learn more about text indexing here:

https://tkdocs.com/tutorial/text.html

You don't need to use add() to add the tag. It is easier to add the tag in the insert.
import tkinter as tk


class Window(tk.Tk):
    def __init__(self):
        super().__init__()
        self.text_tag = 0
        self.text_area = tk.Text(self, wrap="word")
        self.text_area.pack(expand=True, fill=tk.BOTH)

    def update_text(self, text, clear_first=False, bg_color=None):
        if clear_first:
            self.text_area.delete(1.0, tk.END)
        if bg_color is None:
            self.text_area.insert(tk.END, text)
        else:
            tag_name = f"bg_color_{self.text_tag}"
            self.text_tag += 1
            self.text_area.insert(tk.END, text, tag_name)
            self.text_area.tag_config(tag_name, background=bg_color)


window = Window()
window.update_text("This is regular text.")
window.update_text(" This is red text.", bg_color="pink")
window.update_text(" This is blue text.", bg_color="lightblue")
window.update_text(" This is yellow text.", bg_color="yellow")
window.update_text(" Back to normal text.")

window.mainloop()
It is unusual to have random tags. I would create a palette of tags that can be used to highlight text.
import tkinter as tk


class Window(tk.Tk):
    def __init__(self):
        super().__init__()
        self.text_area = tk.Text(self, wrap="word")
        self.text_area.pack(expand=True, fill=tk.BOTH)

    def update_text(self, text, clear_first=False, tags=None):
        if clear_first:
            self.text_area.delete(1.0, tk.END)
        self.text_area.insert(tk.END, text, tags)

    def tag(self, name, **kwargs):
        self.text_area.tag_config(name, **kwargs)


window = Window()
window.tag("hilite", background="yellow")
window.tag("underline", underline=1)
window.update_text("This is normal text.")
window.update_text(" This is highlited text.", tags=("hilite",))
window.update_text(" This is underlined text.", tags=("underline",))
window.update_text(" This text is hilighted and underlined.", tags=("hilite", "underline"))
window.update_text(" Back to normal text.")

window.mainloop()
Reply


Forum Jump:

User Panel Messages

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