-3

I've used this question but can't seem to do it again later. I call it with root.after later but then it does nothing.
my code is:

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")
root = Tk()
T = CustomText(root).pack()
T.tag_configure("red",foreground="#ff0000")
def highlighttext():
    T.highlight_pattern('hello', 'red')
    root.after(10, highlighttext)
root.after(10, highlighttext)
root.mainloop()

Thanks for the help.

Sytze
  • 39
  • 1
  • 10

1 Answers1

1

Fixes

  • widget.pack() returns None, so your T variable will be None. You need to pack your widget after initialization.
  • A function named higlighttext doesn't exist, fix your after method inside the highlighttext method.
  • Remove the after method outside highlighttext method.

Suggestions

Highlighting words with after method seems inefficient and it may not work as expected. Most of the code editors out there make use of the Text Modified events generated by text widgets.

The code for <<TextModified>> event below is taken from Bryan Oakley's answer to one of the previous questions asked in stackoverflow.

import tkinter as tk

class CustomText(tk.Text):
    """A text widget with a new method, highlight_pattern()
    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)

        # 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

    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
            # degenerate pattern which matches zero-length strings
            if count.get() == 0: break 
            self.mark_set("matchStart", index)
            self.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
            self.tag_add(tag, "matchStart", "matchEnd")

root = tk.Tk()

text = CustomText()
text.pack()
text.tag_configure("red", foreground="#ff0000")

def highlighttext(*args):
    text.highlight_pattern("hello", "red")

text.bind("<<TextModified>>", highlighttext)

root.mainloop()

Complete code

With all the fixes applied, your code would look as following

import tkinter as tk

class CustomText(tk.Text):
    '''A text widget with a new method, highlight_pattern()
    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")

root = tk.Tk()

T = CustomText(root)
T.pack()
T.tag_configure("red",foreground="#ff0000")

def highlighttext():
    T.highlight_pattern('hello', 'red')
    root.after(1000, highlighttext)

highlighttext()
root.mainloop()
Billy
  • 1,157
  • 1
  • 9
  • 18