Цикл while слишком медленный в tkinter

#python #tkinter #while-loop

#python #tkinter #цикл while

Вопрос:

Когда я создаю цикл while в tkinter, он выполняется слишком медленно.

Вот код:

 from tkinter import *
import threading

root = Tk()

line = 1
col = 0
loop_count = 1

def highlight_one_by_one():
    global col , loop_count
    while True:
        text.tag_add("highlight" , f"{line}.{col}" , f"{line}.{col   1}")
        text.tag_config("highlight" , foreground = "yellow" , background = "blue")
        col  = 1
        loop_count  = 1
        if loop_count >= len(text.get(1.0 , END)):
            print("done")
            break

text = Text(root, width = 69 , height = 25 , font = "Consolas 14")
text.grid(row=0 , column = 0)

highlight_button = Button(root, text = "Highlight all letters one by one" , command = lambda: threading.Thread(target=highlight_one_by_one , daemon=True).start())
highlight_button.grid(row = 1 , column = 0 , pady = 5)

text.insert(END , "This is a text widgettt"*500)

mainloop()
 

Здесь я создал программу, в которой tkinter будет выделять все буквы в текстовом виджете одну за другой. Но проблема в том, что цикл слишком медленный. Выделение всех букв в текстовом виджете занимает почти 30 секунд. Когда я добавляю полосу прокрутки в текстовый виджет, цикл становится еще медленнее, чем раньше. Я хочу ускорить цикл, чтобы этот цикл мог выделить все буквы менее чем за секунду.

Я знаю, что мог бы использовать text.tag_add("highlight" , 1.0 , END) , но я этого не сделал, потому что в моей другой программе я написал некоторый код, в котором будут выделены только определенные буквы.

Я искал по всему Интернету эту проблему, но не смог найти никакого решения.

Есть ли какой-нибудь способ решить эту проблему?

Было бы здорово, если бы кто-нибудь мог мне помочь.

Комментарии:

1. Это бесконечный цикл, конечно, это займет бесконечное время…

2. Итак, почему вы используете a Thread для выполнения работы? Я не думал, что tkinter это сработает, когда виджеты изменяются в другом потоке.

3. @quamrana, я использую thread, чтобы графический интерфейс не зависал во время выполнения цикла.

4. Хорошо, поэтому обычно с графическими интерфейсами вы бы не использовали длительные циклы. Но когда он вам действительно нужен, тогда, возможно, a Thread будет работать, но тогда вам не следует изменять графический интерфейс из нового потока. И есть способы обойти это, но, видя, как вы хотите, чтобы цикл выполнялся быстро, вы пробовали не использовать поток и заставить кнопку вызывать функцию напрямую?

5. О, я попробовал, и это ускоряет цикл, но все равно зависает графический интерфейс и требуется некоторое время, чтобы выделить весь текст. Но я этого не хочу, так как наше приложение не должно внезапно зависать, когда пользователь работает с ним. Есть ли какой-нибудь способ сократить этот период времени?

Ответ №1:

Я экспериментировал, и это работает быстрее:

 from tkinter import *
import threading

root = Tk()

line = 1
col = 0
loop_count = 1

def highlight_at_once():
    end = len(text.get(1.0 , END))
    col = 0
    text.tag_add("highlight" , f"{line}.{col}" , f"{line}.{col   end}")
    text.tag_config("highlight" , foreground = "yellow" , background = "blue")

def highlight_one_by_one():
    global col , loop_count
    end = len(text.get(1.0 , END))
    while True:
        text.tag_add("highlight" , f"{line}.{col}" , f"{line}.{col   1}")
        
        col  = 1
        loop_count  = 1
        if loop_count >= end:
            print("done")
            break
    text.tag_config("highlight" , foreground = "yellow" , background = "blue")

text = Text(root, width = 69 , height = 25 , font = "Consolas 14")
text.grid(row=0 , column = 0)

highlight_button = Button(root, text = "Highlight all letters one by one" , command = lambda: threading.Thread(target=highlight_one_by_one , daemon=True).start())
#highlight_button = Button(root, text = "Highlight all letters one by one" , command = highlight_at_once)
highlight_button.grid(row = 1 , column = 0 , pady = 5)

text.insert(END , "This is a text widgettt"*500)

mainloop()
 

Комментарии:

1. условно говоря, 1.0 должно быть "1.0" — текстовые индексы — это строки, а не числа с плавающей запятой. Но да, выделение групп символов будет намного, намного быстрее, чем выполнение по одному за раз.