python tkinter文本小部件中的Pygments语法高亮显示



我一直在尝试将语法高亮显示与tkinter文本小部件结合起来。然而,使用这篇文章中的代码,我无法让它发挥作用。没有错误,但文本没有高亮显示,每个字符后面都会跳过一行。如果有更好的方法将语法高亮显示与tkinter文本小部件结合在一起,我会很高兴听到它

import Tkinter
import ScrolledText
from pygments import lex
from pygments.lexers import PythonLexer
root = Tkinter.Tk(className=" How do I put an end to this behavior?")
textPad = ScrolledText.ScrolledText(root, width=100, height=80)
textPad.tag_configure("Token.Comment", foreground="#b21111")
code = textPad.get("1.0", "end-1c")
# Parse the code and insert into the widget
def syn(event=None):
for token, content in lex(code, PythonLexer()):
textPad.insert("end", content, str(token))
textPad.pack()
root.bind("<Key>", syn)
root.mainloop()

到目前为止,我还没有找到解决这个问题的方法(否则我就不会在这里发帖了)。任何关于语法高亮显示tkinter文本小部件的帮助都将不胜感激。

注意:这是在带有Windows7的python 2.7上。

您链接到的问题中的代码更多地是为了突出显示已经存在的文本,而看起来您正试图在键入时突出显示它。

我可以给你一些建议,让你开始,尽管我从来没有这样做过,也不知道什么是最有效的解决方案。这个答案中的解决方案只是一个起点,不能保证它真的适合你的问题。

简短的同义词是:不要设置插入任何内容的绑定。相反,只需突出显示默认绑定插入的内容。

要做到这一点,第一步是绑定<KeyRelease>而不是<Key>。不同之处在于,<KeyRelease>将在插入字符后发生,而<Key>发生在插入字符前

其次,您需要从lexer获取令牌,并将标记应用于每个令牌的文本。为此,您需要跟踪lexer在文档中的位置,然后使用令牌的长度来确定令牌的末尾。

在下面的解决方案中,我创建了一个标记("range_start")来指定文件中pygments-lexer所在的当前位置,然后根据pygments返回的令牌的开始和长度来计算标记"range_end"。面对多字节字符,我不知道这有多健壮。现在,让我们假设为单字节字符。

def syn(event=None):
textPad.mark_set("range_start", "1.0")
data = textPad.get("1.0", "end-1c")
for token, content in lex(data, PythonLexer()):
textPad.mark_set("range_end", "range_start + %dc" % len(content))
textPad.tag_add(str(token), "range_start", "range_end")
textPad.mark_set("range_start", "range_end")

这是非常低效的,因为它在每次按键时都会将高亮显示重新应用于整个文档。有一些方法可以最大限度地减少这种情况,比如只在每个单词后面突出显示,或者当GUI空闲时,或者其他某种触发。

要突出显示某些单词,可以这样做:

textarea.tag_remove("tagname","1.0",tkinter.END)
first = "1.0"
while(True):
first = textarea.search("word_you_are_looking_for", first, nocase=False, stopindex=tkinter.END)
if not first:
break
last = first+"+"+str(len("word_you_are_looking_for"))+"c"
textarea.tag_add("tagname", first, last)
first = last
textarea.tag_config("tagname", foreground="#00FF00")

最新更新