我正在为 tkinter 文本小部件开发拼写检查器。我已经让它工作了,以便用户可以选择不正确的单词并替换文本小部件中不正确单词的所有实例。但是,如果该词出现在另一个词中,它也会替换它。我不要这个。
例如:假设用户有这样一句话:Hello how ay you today
他们将单词“ are ”拼错为“ ay ”,他们可以右键单击它以替换所有实例或将单词“ ay ”替换为“ are ”。
我的问题是,字符串“ ay ”出现在“今天”中。这意味着当用户右键单击“ ay ”时,它会将“今天”变成“ todare ”——将“今天”中的“ ay ”替换为“ are ”
为了替换这个词,我使用了搜索功能。我想检查一下拼写错误的单词两边的字符是否是空格,但我不知道如何实现它。下面是我的代码(注意 - 这大大简化了,我的实际代码有数千行长。在实际程序中,按钮是一个上下文菜单):
from spellchecker import SpellChecker
root = Tk()
notepad = Text(root)
notepad.pack()
spell_dict = SpellChecker()
def check_spelling(event):
global spell_dict
misspelt_words_list = []
paragraph_list = notepad.get('1.0', END).strip('\n').split()
notepad.tag_config('misspelt_word_tag', foreground='red', underline=1)
for word in paragraph_list:
if (word not in spell_dict) and (word not in misspelt_words_list):
misspelt_words_list.append(word)
elif (word in misspelt_words_list) and (word in spell_dict):
misspelt_words_list.remove(word)
notepad.tag_remove('misspelt_word_tag', 1.0, END)
for misspelt_word in misspelt_words_list:
misspelt_word_offset = '+%dc' % len(misspelt_word)
pos_start = notepad.search(misspelt_word, '1.0', END)
while pos_start:
pos_end = pos_start + misspelt_word_offset
notepad.tag_add("misspelt_word_tag",pos_start,pos_end)
pos_start = notepad.search(misspelt_word,pos_end,END)
button = Button(root, text = "This is a test", command = check_spelling)
button.pack()
root.mainloop()
就像我之前说的,如果用户写了ll ll hello
' ll ' 拼写错误的地方(假设程序将把它改正为 I'll),当用户按下按钮时,它应该替换所有写成 ' ll ' 的单词,而不是替换“你好”中的“ ll ”。
这: ll ll hello
-> I'll I'll hello
,不是: ll ll hello
->I'll I'll heI'llo
谢谢你的帮助。
(我使用的是带有 Python 3.7 的 Windows 10)
解决您的问题的方法是使用正则表达式。正则表达式可让您搜索的不仅仅是文本。您还可以搜索模式和其他元字符。例如,表达式只能匹配一行开头或单词开头的字符串。
在您的情况下,您想找到整个单词。在文本小部件search
方法的上下文中,可以通过用\m
(词的开头)和\M
(词的结尾)包围您正在搜索的字符串来搜索整个词。
例如,要仅搜索整个单词的“ll”,您应该搜索\mll\M
。因为反斜杠在python中是一个特殊字符,我们需要将反斜杠传递给search
方法,所以需要对其进行保护。最简单的方法是使用原始字符串。
因此,给定变量中的一个单词(例如:)word="ll"
,我们可以创建一个如下所示的模式:
pattern = r'\m{}\M'.format(word)
要在搜索中使用该模式,我们需要regexp
将该search
方法的参数设置为True
。还有一些其他的事情需要做。我们想让search
方法告诉我们有多少字符与模式匹配。在搜索“ll”的情况下,我们知道它总是两个字符,但一个很好的通用解决方案是让搜索机制告诉我们。我们可以通过将 an 传递IntVar
给search
方法来做到这一点。
我们需要做的另一件事是确保搜索在小部件的末尾停止,否则,它将绕到开头并永远继续搜索。
一旦我们准备好所有这些,我们就可以在文本小部件中搜索字符串“ll”,仅作为整个单词,如下所示:
countvar = IntVar()
pos = "1.0"
pattern = r'\mll\M'
pos = notepad.search(pattern, pos, "end", count=countvar, regexp=True)
pos_end = notepad.index("{} + {} chars".format(pos, countvar.get()))
这样,pos
标志着比赛的开始,也pos_end
标志着比赛的结束。如果pos
是空字符串,那么我们知道 tkinter 没有找到匹配项(在这种情况下我们可以跳过计算pos_end
)。
将所有这些放在一起,我们可以创建一个通用函数,用于查找并突出显示列表中的所有单词,如下所示:
def highlight_words(widget, tag, word_list):
"""Find all whole words in word_list and apply the given tag"""
widget.tag_remove(tag, "1.0", END)
countvar = IntVar()
for word in word_list:
pos = "1.0"
pattern = r"\m{}\M".format(word)
while widget.compare(pos, "<", "end"):
pos = widget.search(pattern, pos, "end", count=countvar, regexp=True)
if pos:
pos_end = widget.index("{} + {} chars".format(pos, countvar.get()))
widget.tag_add(tag,pos,pos_end)
pos = pos_end
else:
break
我们可以这样使用这个函数:
root = Tk()
notepad = Text(root)
notepad.pack()
notepad.tag_configure("misspelt_word_tag", background="pink")
notepad.insert("end", "ll ll hello")
misspelt_word_list = ['ll']
highlight_words(notepad, "misspelt_word_tag", misspelt_word_list)
root.mainloop()
text widgetsearch
方法中使用的正则表达式与 python 正则表达式略有不同。例如,python 用于\b
表示单词的开头或结尾,而该search
方法使用\m
and \M
。有关该search
方法使用的表达式语法的详细说明,请参阅 Tcl 的re_syntax 手册页
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句