如何突出显示tkinter中的特定单词?

时间:2016-01-15 20:02:05

标签: python text tkinter

我需要在tkinter框架中突出显示文本中的特定单词。为了找到这个词,我在html中添加了一个balise。所以在"你好我喜欢的房子中有一个"我想强调一下这个词" house"。

我的框架定义如下:

class FrameCodage(Frame): self.t2Codage = Text(self, height=20, width=50)

我用以下代码插入我的文字:fenetre.fCodage.t2Codage.insert(END, res),res是包含我的文字的变量。

我在另一篇文章中看到了这段代码:

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.
    '''

    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
        self.mark_set("matchStart", index)
        self.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
        self.tag_add(tag, "matchStart", "matchEnd")

但是他们很少有我不明白的事情:我怎样才能将这个功能应用到我的案例中?我什么时候打电话给这个职能?在我的案例中,模式和标签是什么?我是Tkinter的初学者,所以不要犹豫向我解释这段代码或其他代码。

2 个答案:

答案 0 :(得分:2)

而不是:

class FrameCodage(Frame):
    self.t2Codage = Text(self, height=20, width=50)

......这样做:

class FrameCodage(Frame):
    self.t2Codage = CustomText(self, height=20, width=50)

接下来,创建一个“突出显示”标记,然后根据需要对其进行配置:

self.t2Codage.tag_configure("highlight", foreground="red")

最后,您可以将highlight_pattern方法称为标准方法:

self.t2Codage.highlight_pattern(r"\|.*?\|", "red", regexp=True)

答案 1 :(得分:1)

下面是我为解决这个问题而创建的小部件,希望对您有所帮助。

try: import tkinter as tk
except ImportError: import Tkinter as tk

class code_editor(tk.Text):
    def __init__(self, parent, case_insensetive = True, current_line_colour = '', word_end_at = r""" .,{}[]()=+-*/\|<>%""", tags = {}, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)
        
        self.bind("<KeyRelease>", lambda e: self.highlight())
        
        self.case_insensetive = case_insensetive
        self.highlight_current_line = current_line_colour != ''
        self.word_end = word_end_at
        self.tags = tags
        
        if self.case_insensetive:
            for tag in self.tags:
                self.tags[tag]['words'] = [word.lower() for word in self.tags[tag]['words']]
        
        #loops through the syntax dictionary to creat tags for each type
        for tag in self.tags:
            self.tag_config(tag, **self.tags[tag]['style'])
        
        if self.highlight_current_line:
            self.tag_configure("current_line", background = current_line_colour)
            self.tag_add("current_line", "insert linestart", "insert lineend+1c")
            self.tag_raise("sel")
        
    #find what is the last word thats being typed.
    def last_word(self):
        line, last = self.index(tk.INSERT).split('.')
        last=int(last)
        
        #this limit issues when user is a fast typer
        last_char = self.get(f'{line}.{int(last)-1}', f'{line}.{last}')
        while last_char in self.word_end and last > 0:
            last-=1          
            last_char = self.get(f'{line}.{int(last)-1}', f'{line}.{last}')
            
        first = int(last)
        while True:
            first-=1
            if first<0: break
            if self.get(f"{line}.{first}", f"{line}.{first+1}") in self.word_end:
                break
        return {'word': self.get(f"{line}.{first+1}", f"{line}.{last}"), 'first': f"{line}.{first+1}", 'last': f"{line}.{last}"}
    
    #highlight the last word if its a syntax, See: syntax dictionary on the top.
    #this runs on every key release which is why it fails when the user is too fast.
    #it also highlights the current line
    def highlight(self):
        
        if self.highlight_current_line:
            self.tag_remove("current_line", 1.0, "end")
            self.tag_add("current_line", "insert linestart", "insert lineend+1c")
        
        lastword = self.last_word()
        wrd = lastword['word'].lower() if self.case_insensetive else lastword['word']
        
        for tag in self.tags:
            if wrd in self.tags[tag]['words']:
                self.tag_add(tag, lastword['first'], lastword['last'])
            else:
                self.tag_remove(tag, lastword['first'], lastword['last'])
        
        self.tag_raise("sel")
        
#### example ####
if __name__ == '__main__':
    # from pyFilename import code_editor
    
    ms = tk.Tk()
    
    example_text = code_editor(
        parent = ms,
        case_insensetive = True, #True by default.
        current_line_colour = 'grey10', #'' by default which will not highlight the current line.
        word_end_at = r""" .,{}[]()=+-*/\|<>%""", #<< by default, this will till the class where is word ending.
        tags = {#'SomeTagName': {'style': {'someStyle': 'someValue', ... etc}, 'words': ['word1', 'word2' ... etc]}} this tells it to apply this style to these words
            "failSynonyms": {'style': {'foreground': 'red', 'font': 'helvetica 8'}, 'words': ['fail', 'bad']},
            "passSynonyms":{'style': {'foreground': 'green', 'font': 'helvetica 12'}, 'words': ['Pass', 'ok']},
            "sqlSyntax":{'style': {'foreground': 'blue', 'font': 'italic'}, 'words': ['select', 'from']},
            },
        font='helvetica 10 bold',   #Sandard tkinter text arguments
        background = 'black',       #Sandard tkinter text arguments
        foreground = 'white'        #Sandard tkinter text arguments
    )    
    
    example_text.pack()
    ms.mainloop()