#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"
— текстовые индексы — это строки, а не числа с плавающей запятой. Но да, выделение групп символов будет намного, намного быстрее, чем выполнение по одному за раз.