对文本小部件中的字符进行标记会减慢程序的速度

时间:2018-06-13 12:55:34

标签: python tkinter tokenize

当我将一些python脚本的内容插入文本小部件时,可以快速突出显示内容。插入内容后,也可以突出显示手动键入的新插入内容。但是,在将某些python脚本的内容插入文本小部件后,新插入的内容会快速插入,但会突然显示

我该怎么做才能解决这个问题?

提前致谢。

代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
if sys.version_info.major == 2:
    exit()
elif sys.version_info.major == 3:
    import io
    import keyword
    import builtins
    import tokenize
    import threading
    import tkinter as tk


root = tk.Tk()
text = tk.Text(master=root, fg="white", bg="black", font="TkDefaultFont 10")
text.pack(fill="both", expand=True)

count = 0


def colorize(*args):
    global count
    row1, col1 = args[0].start
    start = str(row1) + "." + str(col1)
    row2, col2 = args[0].end
    end = str(row2) + "." + str(col2)
    text.tag_add(str(count), start, end)
    try:
        text.tag_config(str(count), foreground=args[1], font=args[2])
    except IndexError:
        text.tag_config(str(count), foreground=args[1])
    count += 1


def search():
    while True:
        try:
            for i in tokenize.tokenize(io.BytesIO(text.get("1.0", "end").encode("utf-8")).readline):
                if i.type == 1:
                    if i.string in keyword.kwlist:
                        colorize(i, "orange")
                    elif i.string in dir(builtins):
                        colorize(i, "blue")
                    else:
                        colorize(i, "white")
                elif i.type == 2:
                    colorize(i, "cyan")
                elif i.type == 3:
                    colorize(i, "purple")
                elif i.type == 53:
                    if i.string == "," or i.string == "." or i.string == ":":
                        colorize(i, "orange")
                    elif i.string == "(" or i.string == ")" or i.string == "[" \
                            or i.string == "]" or i.string == "{" or i.string == "}":
                        colorize(i, "darkred")
                    else:
                        colorize(i, "green")
                elif i.type == 57:
                    colorize(i, "grey", "TkDefaultFont 10 italic")
        except tokenize.TokenError:
            pass


thread = threading.Thread(target=search)
thread.daemon = True
thread.start()
thread.join(1)
root.mainloop()

1 个答案:

答案 0 :(得分:1)

问题解决了。

已从代码中删除了线程模块。现在,解析操作使用键绑定("<KeyRelease>")完成。因此,search()函数中的while循环也被删除了。

colorize(*args)功能已更改为:

def colorize(*args):
    global count
    row = text.index("insert").split(".")[0]
    col1 = args[0].start[-1]
    start = row + "." + str(col1)
    col2 = args[0].end[-1]
    end = row + "." + str(col2)
    text.tag_add(str(count), start, end)
    try:
        text.tag_config(str(count), foreground=args[1], font=args[2])
    except IndexError:
        text.tag_config(str(count), foreground=args[1])
    count += 1

根据此功能,行变量设置为插入位置以停止重复着色整个内容。因此只需要扫描和着色最后一行。

为不同的情况定义了两种解析方法。

当插入位置位于最后一行时,将激活第一个解析器。我之前帖子的search()方法之间的核心没有更改第一个解析器。当想要在窗口小部件中粘贴复制的代码时,第二个解析器被激活。

这是第二个解析器方法:

keysym = set()


def parser_2(*args):
    global keysym
    keysym = set()
    for i in range(int(args[0])):
        text.mark_set("insert", "{}.{}".format(i + 1, args[1]))
        parser_1(text.get("{}.0".format(i + 1), "{}.0".format(i + 2)))
        text.mark_set("insert", "{}.{}".format(args[0], args[1]))

将复制的代码插入窗口小部件后,插入位置会发生变化。因此,如果我们在for循环中访问所有行直接或反向并设置所有这些访问行的标记并使用参数调用parser_1(*args)函数(参数是访问行和插入位置列)然后再次将标记设置为正常插入位置,复制的内容可以着色一次。当用户键入 ctrl + v 或用户想要使用右键菜单将代码粘贴到窗口小部件时,这是着色的快捷功能。

最后一个函数(select_parser(event))用于根据不同情况选择解析器。

def select_parser(event):
    row, col = text.index("insert").split(".")
    if event.keysym == "Control_L":
        keysym.add(event.keysym)
    elif event.keysym == "v" or event.keysym == "V":
        keysym.add(event.keysym)
        if "Control_L" in keysym:
            parser_2(row, col)
    elif event.keysym == "Control_R":
        keysym.add(event.keysym)
        if "v" in keysym or "V" in keysym:
            parser_2(row, col)
    else:
        parser_1(text.get("{}.0".format(row), "{}.0".format(int(row) + 1)))

一种情况是当用户输入&#34; Control_L&#34; 时。如果用户对其进行输入,则会将其添加到全局中定义的 keysym 集中。

另一种情况是用户输入&#34; v&#34; &#34; V&#34; 。如果用户输入其中一个,则event.keysym也会添加到 keysym 中。并且在此案例中定义了一个不同的条件,用于检查&#34; Control_L&#34; 是否设置在 keysym 中。如果是,则调用第二个解析方法。 keysym 在第二个解析器方法中重新定义。

另一种情况是用户输入&#34; Control_R&#34; 。如果用户输入它,它也会被添加到 keysym 中。在此定义的另一个条件是检查&#34; v&#34; &#34; V&#34; 是否在 keysym中设置与否。 (当我们输入&#34; Control_R + v&#34; 时,首先&#34; v&#34; 会添加到 keysym 中但是当我们输入&#34; Control_L + v&#34; 时,首先&#34; Control_L&#34; 会添加到 keysym 设置中。)如果&#34; v&#34; &#34; V&#34; 设置为 keysym ,则第二种解析方法叫做。 keysym 在第二个解析器方法中重新定义。

最后一种情况是用户类型与上述键不同。在这种情况下,将调用第一个解析器方法。

<强>代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
if sys.version_info.major == 2:
    exit()
elif sys.version_info.major == 3:
    import io
    import keyword
    import builtins
    import tokenize
    import tkinter as tk


root = tk.Tk()
text = tk.Text(master=root, fg="white", bg="black", font="TkDefaultFont 10")
text.pack(fill="both", expand=True)

count = 0


def colorize(*args):
    global count
    row = text.index("insert").split(".")[0]
    col1 = args[0].start[-1]
    start = row + "." + str(col1)
    col2 = args[0].end[-1]
    end = row + "." + str(col2)
    text.tag_add(str(count), start, end)
    try:
        text.tag_config(str(count), foreground=args[1], font=args[2])
    except IndexError:
        text.tag_config(str(count), foreground=args[1])
    count += 1


def parser_1(*args):
    try:
        for i in tokenize.tokenize(io.BytesIO(
                args[0].encode("utf-8")).readline):
            if i.type == 1:
                if i.string in keyword.kwlist:
                    colorize(i, "orange")
                elif i.string in dir(builtins):
                    colorize(i, "blue")
                else:
                    colorize(i, "white")
            elif i.type == 2:
                colorize(i, "cyan")
            elif i.type == 3:
                colorize(i, "purple")
            elif i.type == 53:
                if i.string == "," or i.string == "." or i.string == ":":
                    colorize(i, "orange")
                elif i.string == "(" or i.string == ")" or i.string == "[" \
                        or i.string == "]" or i.string == "{" or i.string == "}":
                    colorize(i, "darkred")
                else:
                    colorize(i, "green")
            elif i.type == 57:
                colorize(i, "grey", "TkDefaultFont 10 italic")
    except tokenize.TokenError:
        pass


keysym = set()


def parser_2(*args):
    global keysym
    keysym = set()
    for i in range(int(args[0])):
        text.mark_set("insert", "{}.{}".format(i + 1, args[1]))
        parser_1(text.get("{}.0".format(i + 1), "{}.0".format(i + 2)))
        text.mark_set("insert", "{}.{}".format(args[0], args[1]))


def select_parser(event):
    row, col = text.index("insert").split(".")
    if event.keysym == "Control_L":
        keysym.add(event.keysym)
    elif event.keysym == "v" or event.keysym == "V":
        keysym.add(event.keysym)
        if "Control_L" in keysym:
            parser_2(row, col)
    elif event.keysym == "Control_R":
        keysym.add(event.keysym)
        if "v" in keysym or "V" in keysym:
            parser_2(row, col)
    else:
        parser_1(text.get("{}.0".format(row), "{}.0".format(int(row) + 1)))


text.bind("<KeyRelease>", select_parser)
root.mainloop()