我正试图把一个简单的文本框与拼写检查集成在一起。我已经看过pyenchant,我不确定如何将其集成到tkinter文本框中,或者我是否应该查看一个完全不同的拼写检查器。
import enchant
import tkinter as tk
from enchant.tokenize import get_tokenizer
#Tokenizer for the spell check
sc = get_tokenizer("en_US")
#Window
window = tk.Tk()
#Text box to be checked
words = tk.Text(width=50)
sc
#Window layout
words.grid(row=1, column=1, padx=1.5, pady=1.5)
window.mainloop()
理想情况下,您需要一些东西来告诉您文本内容已经更改,然后获取数据并在其上运行魔咒函数。然后,您可以使用文本小部件标记来指示拼写错误,以更改单词的外观。
下面是一个例子。
"""Text widget with spell checking.
Requires installation of pyenchant
"""
import tkinter as tk
import tkinter.ttk as ttk
from enchant import Dict, tokenize
import sys
class SpellcheckText(tk.Text):
locale = 'en_US'
def __init__(self, master, **kwargs):
self.afterid = None
self.corpus = Dict(self.locale)
self.tokenize = tokenize.get_tokenizer(self.locale)
super(SpellcheckText, self).__init__(master, **kwargs)
self._proxy = self._w + "_proxy"
self.tk.call("rename", self._w, self._proxy)
self.tk.createcommand(self._w, self._proxycmd)
self.tag_configure('sic', foreground='red')
self.bind('<<TextModified>>', self.on_modify)
def _proxycmd(self, command, *args):
"""Intercept the Tk commands to the text widget and if eny of the content
modifying commands are called, post a TextModified event."""
cmd = (self._proxy, command)
if args:
cmd = cmd + args
result = self.tk.call(cmd)
if command in ('insert', 'delete', 'replace'):
self.event_generate('<<TextModified>>')
return result
def on_modify(self, event):
"""Rate limit the spell-checking with a 100ms delay. If another modification
event comes in within this time, cancel the after call and re-schedule."""
try:
if self.afterid:
self.after_cancel(self.afterid)
self.afterid = self.after(100, self.on_modified)
except Exception as e:
print(e)
def on_modified(self):
"""Handle the spell check once modification pauses.
The tokenizer works on lines and yields a list of (word, column) pairs
So iterate over the words and set a sic tag on each spell check failed word."""
self.afterid = None
self.tag_remove('sic', '1.0', 'end')
num_lines = [int(val) for val in self.index("end").split(".")][0]
for line in range(1, num_lines):
data = self.get(f"{line}.0 linestart", f"{line}.0 lineend")
for word,pos in self.tokenize(data):
check = self.corpus.check(word)
print(f"{word},{pos},{check}")
if not check:
start = f"{line}.{pos}"
end = f"{line}.{pos + len(word)}"
self.tag_add("sic", start, end)
class App(ttk.Frame):
def __init__(self, master, **kwargs):
super(App, self).__init__(master, **kwargs)
master.wm_withdraw()
self.create_ui()
self.grid(row=0, column=0, sticky=tk.NSEW)
master.grid_rowconfigure(0, weight=1)
master.grid_columnconfigure(0, weight=1)
master.wm_deiconify()
def create_ui(self):
text = SpellcheckText(self)
vs = ttk.Scrollbar(self, command=text.yview)
text.configure(yscrollcommand=vs.set)
text.grid(row=0, column=0, sticky=tk.NSEW)
vs.grid(row=0, column=1, sticky=tk.NSEW)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
def main(args=None):
root = tk.Tk()
app = App(root)
root.mainloop()
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))