How to Highlight Text in a Tkinter Text Widget

How to highlight text in a tkinter Text widget

It's the right widget to use for these purposes. The basic concept is, you assign properties to tags, and you apply tags to ranges of text in the widget. You can use the text widget's search command to find strings that match your pattern, which will return you enough information apply a tag to the range that matched.

For an example of how to apply tags to text, see my answer to the question Advanced Tkinter text box?. It's not exactly what you want to do but it shows the basic concept.

Following is an example of how you can extend the Text class to include a method for highlighting text that matches a pattern.

In this code the pattern must be a string, it cannot be a compiled regular expression. Also, the pattern must adhere to Tcl's syntax rules for regular expressions.

class CustomText(tk.Text):
'''A text widget with a new method, highlight_pattern()

example:

text = CustomText()
text.tag_configure("red", foreground="#ff0000")
text.highlight_pattern("this should be red", "red")

The highlight_pattern method is a simplified python
version of the tcl code at http://wiki.tcl.tk/3246
'''
def __init__(self, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)

def highlight_pattern(self, pattern, tag, start="1.0", end="end",
regexp=False):
'''Apply the given tag to all text that matches the given pattern

If 'regexp' is set to True, pattern will be treated as a regular
expression according to Tcl's regular expression syntax.
'''

start = self.index(start)
end = self.index(end)
self.mark_set("matchStart", start)
self.mark_set("matchEnd", start)
self.mark_set("searchLimit", end)

count = tk.IntVar()
while True:
index = self.search(pattern, "matchEnd","searchLimit",
count=count, regexp=regexp)
if index == "": break
if count.get() == 0: break # degenerate pattern which matches zero-length strings
self.mark_set("matchStart", index)
self.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
self.tag_add(tag, "matchStart", "matchEnd")

How to highlight a word or an alphabet in Tkinter Text widget?

I made a simple program to select all the Hellos in the Text:

from tkinter import *

def find_nth(haystack, needle, n): #Function to find the index of nth substring in a string
start = haystack.find(needle)
while start >= 0 and n > 1:
start = haystack.find(needle, start+len(needle))
n -= 1
return start

def find():
word = "H" #Targetted Word
text, line = tx.get("1.0",END), 0 #text getting text of the widget
text = text.split("\n") #splitting and getting list on the newlines
for x, i in enumerate(text): #Looping through that list
if word in i: #if targetted word is in the xth string i of the list
for e in range(0, i.count(word)):
index = find_nth(i, word, e+1) #Getting the index of the word
start = float(str(x+1)+"."+str(index)) #Making the indices for tkinter
end = float(str(x+1)+"."+str(index+len(word))) #Making the indices for tkinter
tx.focus() #Focusing on the Text widget to make the selection visible
tx.tag_add("sel", start, end) #selecting from index start till index end
root = Tk()
tx = Text(root)
tx.insert(END, "World Hello World\nHello World Hello Hello\nHello Hello")
bu = Button(root, text = "Find Hello", command = find)
tx.pack()
bu.pack()
root.mainloop()

Output:

Sample Image

I used this answer for help.

How do I highlight (select) text in Text widget with a button click?

Try

entry.tag_add('sel', '1.0', 'end')

or

entry.tag_add('sel', '1.0', 'end-1c')

Highlight the entire line length in Tkinter Text widget

Your highlight needs to include the newline character in order to span the full width of the widget. Add "+1c" (plus one character) to your second index:

text.tag_add("highlight", "{}.0".format(n), "{}.end+1c".format(n))


Related Topics



Leave a reply



Submit