【问题标题】:How to highlight a specific word in tkinter?如何突出显示 tkinter 中的特定单词?
【发布时间】:2016-01-15 20:02:05
【问题描述】:

我需要在 tkinter 框架内突出显示文本中的特定单词。为了找到这个词,我在 html 中放了一个应答器。所以在像“你好,我在 |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 的初学者,所以请不要犹豫,向我解释这段代码或其他代码。

【问题讨论】:

    标签: python text tkinter


    【解决方案1】:

    而不是这个:

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

    ... 这样做:

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

    接下来,创建一个“highlight”标签,然后根据需要进行配置:

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

    最后,您可以像调用标准方法一样调用highlight_pattern 方法:

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

    【讨论】:

    • 感谢您帮助我。 “CustomText”给我一个“未定义”的错误。另外,我不会在与 FrameCodage 相同类的框架中输入我的文本。那么,我如何调用我的函数呢?我尝试了“FrameCodage.t2Codage.highlight_pattern(...)”,但它不起作用。为了确定,我必须在 "self.t2Codage = Text(self, height=20, width=50)" 之后定义标签?
    • @pioupiou1211:您必须在创建小部件后添加标签;在您创建它之前,它是不可能调用的。插入文本的位置或时间无关紧要。插入文本后,您可以调用highlight_text 方法。它不会自动发生。
    • 好的,然后我在插入文本之前调用了该方法,因为这无关紧要。但我有这个错误:self.t2Codage.highlight_pattern(r"\|.*?\|", "red", regexp=True) AttributeError: 'Text' object has no attribute 'highlight_pattern'
    • @pioupiou1211:阅读错误信息。注意它是怎么说的'Text' object?如果你使用这个类,它会说'CustomText' object
    • 哦,是的,对不起,我不明白我必须创建类 CustomText。现在一切都设置好了,但我不知道如何调用该方法。之后我输入了文本,我做了fenetre.fCodage.t2Codage.highlight_pattern(r"\|.*?\|", "red", regexp=True) ,但它不起作用。我没有收到错误消息,但没有突出显示。
    【解决方案2】:

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

    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()
    

    【讨论】:

    • 非常感谢! @Mohmoud Alhyari
    猜你喜欢
    • 2020-10-11
    • 2019-06-24
    • 2014-03-08
    • 2012-01-29
    • 2018-02-08
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    相关资源
    最近更新 更多