代码之家  ›  专栏  ›  技术社区  ›  dildeolupbiten

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

  •  0
  • dildeolupbiten  · 技术社区  · 6 年前

    当我将一些python脚本的内容插入到文本小部件时,可以快速突出显示这些内容。此外,在插入内容之后,也可以突出显示手动键入的新插入内容。但是,在将一些python脚本的内容插入到文本小部件之后,新的插入是 快速插入但延迟突出显示 .

    我该怎么解决这个问题?

    提前谢谢。

    Codes:

    #!/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 回复  |  直到 6 年前
        1
  •  1
  •   dildeolupbiten    6 年前

    问题解决了。

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

    这个 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
    

    根据此函数,将行变量设置为插入位置,以停止对整个内容重复着色。所以 只有最后一行需要扫描和着色。

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

    当插入位置在最后一行时,将激活第一个解析器。第一个解析器在 搜索() 我上一篇文章的方法。当需要在小部件中粘贴复制的代码时,激活第二个解析器。

    下面是第二种解析器方法:

    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)))
    

    一种情况是当用户键入 “控制” . 如果用户键入,则将其添加到 符号码 在全局中定义的集合。

    另一种情况是当用户键入 “V” “V” . 如果用户键入其中一个,则 event.keysym 添加到 符号码 也设置。在这种情况下定义了一个不同的条件来检查 “控制” 是在 符号码 设置或不设置。如果它在中,则调用第二个解析方法。以及 符号码 在第二个解析器方法中重新定义。

    另一种情况是当用户键入 “控制” . 如果用户键入,则将其添加到 符号码 也设置。这里定义了另一个条件来检查 “V” “V” 是在 符号码 设置或不设置。(当我们打字时 “控制室+V” ,首先 “V” 添加到 符号码 但当我们打字的时候 “控制+V” ,首先 “控制” 添加到 符号码 设置) “V” “V” 是在 符号码 set,调用第二个解析方法。以及 符号码 在第二个解析器方法中重新定义。

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

    Codes:

    #!/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()