Использование символов в текстовом виджете замедляет работу программы - PullRequest
0 голосов
/ 13 июня 2018

Когда я вставляю содержимое некоторого скрипта 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 голосов
/ 15 июня 2018

Проблема была решена.

Модуль потоков был удален из кодов.Теперь операции разбора выполняются с помощью привязки ключей ("<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

В соответствии с этой функцией переменная строки установлена ​​напозиция вставки, чтобы прекратить повторять раскрашивание всего содержимого.Поэтому необходимо сканировать и раскрашивать только последние строки.

Для разных случаев определены два метода синтаксического анализа.

Первый анализатор активируется, когда позиция вставки находится в последнем ряду.Первый парсер не изменился по сути между 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)))

Один случай, когда пользователь вводит "Control_L" .Если пользователь вводит его, он добавляется в набор keysym , который был определен в global.

Другой случай, когда пользователь вводит "v" или "V" .Если пользователь вводит один из них, event.keysym добавляется в набор keysym .И в этом случае определено другое условие, которое проверяет, установлено ли "Control_L" keysym или нет.Если он включен, вызывается второй метод анализа.И keysym переопределяется во втором методе синтаксического анализа.

Другой случай, когда пользователь вводит "Control_R" .Если пользователь вводит его, он также добавляется в набор keysym .Здесь определено еще одно условие, которое проверяет, установлено ли "v" или "V" в keysym или нет.(Когда мы набираем "Control_R + v" , сначала "v" добавляется в набор keysym , но когда мы набираем "Control_L + v" , сначала "Control_L" добавляется в набор keysym .) Если "v" или "V" в 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()
...