为tkinter Text组件添加高级功能

15 投票
2 回答
22916 浏览
提问于 2025-04-16 04:15

我正在做一个简单的消息系统,需要在Tkinter的文本框中添加以下功能:

  1. 拼写检查
  2. 更改字体的选项(针对选中的文字)
  3. 更改字体颜色的选项(针对选中的文字)
  4. 更改字体大小的选项(针对选中的文字)

我知道Tkinter的文本框可以通过标签机制使用多种字体和颜色,但我不太明白怎么利用这些功能。

我该如何利用文本框的功能来实现这些特性呢?具体来说,我该如何改变文字的字体、颜色和大小?另外,我该如何实现拼写检查的功能,比如把拼错的单词用下划线标记或者用不同的颜色显示?

2 个回答

5

1) Tk本身没有内置的拼写检查功能。如果你需要这个功能,可以看看PyEnchant

2) 第3、4点其实并不难(请忽略我之前提到的使用wxPython的建议)。你可以在文本控件的插入方法中,把tag_config作为第三个参数传入。这个参数用来定义你所选内容的配置。

下面的代码是根据Scrolledtext示例和effbot的内容修改而来的,effbot是关于Tk的最佳参考资料。

"""
Some text
hello
"""

from Tkinter import *
from Tkconstants import RIGHT, LEFT, Y, BOTH
from tkFont import Font
from ScrolledText import ScrolledText

def example():
    import __main__
    from Tkconstants import END

    stext = ScrolledText(bg='white', height=10)
    stext.insert(END, __main__.__doc__)

    f = Font(family="times", size=30, weight="bold")
    stext.tag_config("font", font=f)

    stext.insert(END, "Hello", "font")
    stext.pack(fill=BOTH, side=LEFT, expand=True)
    stext.focus_set()
    stext.mainloop()

if __name__ == "__main__":
    example()
37

Tkinter的文本小部件非常强大,但有些高级功能需要自己来实现。它没有内置的拼写检查,也没有直接的按钮来加粗文本等等,不过这些功能其实很容易实现。这个小部件已经具备了所有的能力,只需要知道怎么做就行。

下面的例子给你提供了一个按钮,可以切换选中文本的加粗状态——你可以选择一段字符,然后点击这个按钮来添加或去掉加粗效果。你应该很容易就能扩展这个例子,来实现字体和颜色的变化。

拼写检查也很简单。下面的例子使用了/usr/share/dict/words中的单词(在Windows 7上这个文件几乎肯定不存在,所以你需要提供一个合适的单词列表)。这个例子有点简单,因为它只在你按下空格键时进行拼写检查,但这样做是为了让代码保持简洁。在实际应用中,你可能会想要更智能地决定什么时候进行拼写检查。

import Tkinter as tk
import tkFont

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        ## Toolbar
        self.toolbar = tk.Frame()
        self.bold = tk.Button(name="toolbar", text="bold", 
                              borderwidth=1, command=self.OnBold,)
        self.bold.pack(in_=self.toolbar, side="left")

        ## Main part of the GUI
        # I'll use a frame to contain the widget and 
        # scrollbar; it looks a little nicer that way...
        text_frame = tk.Frame(borderwidth=1, relief="sunken")
        self.text = tk.Text(wrap="word", background="white", 
                            borderwidth=0, highlightthickness=0)
        self.vsb = tk.Scrollbar(orient="vertical", borderwidth=1,
                                command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.vsb.pack(in_=text_frame,side="right", fill="y", expand=False)
        self.text.pack(in_=text_frame, side="left", fill="both", expand=True)
        self.toolbar.pack(side="top", fill="x")
        text_frame.pack(side="bottom", fill="both", expand=True)

        # clone the text widget font and use it as a basis for some
        # tags
        bold_font = tkFont.Font(self.text, self.text.cget("font"))
        bold_font.configure(weight="bold")
        self.text.tag_configure("bold", font=bold_font)
        self.text.tag_configure("misspelled", foreground="red", underline=True)

        # set up a binding to do simple spell check. This merely
        # checks the previous word when you type a space. For production
        # use you'll need to be a bit more intelligent about when
        # to do it.
        self.text.bind("<space>", self.Spellcheck)

        # initialize the spell checking dictionary. YMMV.
        self._words=open("/usr/share/dict/words").read().split("\n")

    def Spellcheck(self, event):
        '''Spellcheck the word preceeding the insertion point'''
        index = self.text.search(r'\s', "insert", backwards=True, regexp=True)
        if index == "":
            index ="1.0"
        else:
            index = self.text.index("%s+1c" % index)
        word = self.text.get(index, "insert")
        if word in self._words:
            self.text.tag_remove("misspelled", index, "%s+%dc" % (index, len(word)))
        else:
            self.text.tag_add("misspelled", index, "%s+%dc" % (index, len(word)))


    def OnBold(self):
        '''Toggle the bold state of the selected text'''

        # toggle the bold state based on the first character
        # in the selected range. If bold, unbold it. If not
        # bold, bold it.
        current_tags = self.text.tag_names("sel.first")
        if "bold" in current_tags:
            # first char is bold, so unbold the range
            self.text.tag_remove("bold", "sel.first", "sel.last")
        else:
            # first char is normal, so bold the whole selection
            self.text.tag_add("bold", "sel.first", "sel.last")

if __name__ == "__main__":
    app=App()
    app.mainloop()

撰写回答