【问题标题】:How to color words in tkinter text box but remove the color if the word is a substring of a string?如何在 tkinter 文本框中为单词着色,但如果单词是字符串的子字符串,则删除颜色?
【发布时间】:2020-09-20 11:59:56
【问题描述】:

我对 tkinter 文本框中的整个 'tags' 东西很陌生输入的字符串,而我想要做的是仅在字符串是完整单词时突出显示字符串,而不是在字符串是字符串的子字符串时突出显示。示例:我想突出显示以下给定文本中出现的“或”:

“我们可以去南港或北港。”

我们可以去南部的pt strong> northern port

“或”以粗斜体形式出现了五次,而应该只有一次。

还有一件事,如何改变引号内文字的颜色? 如果您知道我问题的上述两个部分中任何一个的答案,那将非常有帮助

请帮我解决这个问题...

提前致谢

【问题讨论】:

  • 您尝试过使用单词边界 (\b) 吗?正则表达式应该是\bor\b
  • @RamónMárquez:文本小部件搜索使用Tcl regularexpressions,因此\b 将不起作用。相反,Tcl 使用\m\M 作为字边界。
  • 即使在搜索之后我也找不到\m 的用法。请我提供一个关于如何使用它的例子(使用上面提到的链接代码)

标签: python tkinter text tags


【解决方案1】:

关于 Tcl 正则表达式的详细信息可以找到here。特别是,

\y 仅匹配单词的开头或结尾

因此在.highlight_pattern() 中使用模式r'\yor\y' 只会突出显示单词“或”而不是子字符串。

其次,可以使用正则表达式r'"[^"]+"' 来查找引号之间的文本。 [^"] 表示除引号之外的任何字符。如果您不想突出显示引号,则需要将标签从匹配开始后的一个字符添加到匹配结束前的一个字符。但是,使用这种模式,包含换行符的引用文本将不会被突出显示。如果您还想突出显示包含换行符的引用文本,可以使用正则表达式r'"([^"]|\n)+"'

这是一个基于How to highlight text in a tkinter Text widget的回答的例子

import tkinter as tk

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.
        '''
        self.tag_remove(tag, start, end) # remove tag first
        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")

    def highlight_quoted_text(self, tag, start="1.0", end="end"):
        self.tag_remove(tag, start, end) # remove tag first
        start = self.index(start)
        end = self.index(end)

        count = tk.IntVar()
        while True:
            index = self.search(r'"[^"]+"', start, end,
                                count=count, regexp=True)
            if index == "":
                break

            start = self.index("%s+%sc" % (index, count.get()))
            self.tag_add(tag, "%s+1c" % index, "%s-1c" % start)


root = tk.Tk()
text = CustomText(root)
text.tag_configure('highlight', background='yellow')
text.tag_configure('quoted', background='orange')
text.pack()


text.insert('1.0', "We can go for the southern port or the northern port.\n\"Text surronded by quotes\" and regular text without quotes and \"quoted text again\"")
tk.Button(root, text='Highlight "or"', command=lambda: text.highlight_pattern(r'\yor\y', 'highlight', regexp=True)).pack()
tk.Button(root, text='Highlight quoted', command=lambda: text.highlight_quoted_text('quoted')).pack()

root.mainloop()
    

【讨论】:

  • 好人!! @j_4321,它工作得很好,但你能解释一下如何制作多行字符串吗? r'"([^"]|\n)+"' 的唯一问题是,首先您必须在同一行中输入所有内容,然后如果按 Return,颜色不会改变,但如果按 Return 后我在引号内输入任何内容,则颜色不会改变
  • 例如,如果我首先输入“Yo this is a multiline string”,然后将其分开:“Yo\n this is a \n multiline \n string”它不会创建任何颜色区别但是如果我在“Yo\n this is a \n ulti-multi-penalty line\n string”之间输入任何内容它不会突出显示新输入的单词
  • 我猜这些 cmets 不允许多行,所以我改用 \n
  • 如果突出显示的单词的字符串被删除,关于如何删除标签的任何想法??
  • @prerakl123 对于最后一条评论,您可以在搜索带有.tag_remove(tag, start, end) 的单词/引用文本之前删除标签。我已经编辑了我的答案。
猜你喜欢
  • 2013-01-05
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 2015-10-19
  • 1970-01-01
  • 2013-09-19
相关资源
最近更新 更多