1

When I create a while loop in tkinter, it runs too slow.

Here's the code:

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 widget\t\t"*500)

mainloop()

Here, I have created a program where tkinter will highlight all the letters in the text widget one by one. But the problem is that the loop is too slow. It takes almost 30 seconds to highlight all the letters in the text widget. When I add a scrollbar to the text widget, the loop becomes even slower than before. What I want is to speed up the loop so that this loop can highlight all the letters in less than a second.

I know I could have used text.tag_add("highlight" , 1.0 , END) , but I didn't do that because in my other program, I have written some code where only specific letters will get highlighted.

I searched all over the internet regarding this issue, but couldn't find any solution.

Is there any way to fix this problem?

It would be great if anyone could help me out.

14
  • 2
    It's an infinite loop, of course it will take infinite time... Commented Jan 19, 2021 at 16:59
  • So, why do you use a Thread to do the work? I didn't think that tkinter would work when widgets were being modified in a different thread. Commented Jan 19, 2021 at 17:19
  • @quamrana , I am using thread so that the GUI does not freeze while the loop is running. Commented Jan 19, 2021 at 17:22
  • Ok, so normally with GUIs you wouldn't use long running loops. But when you really need one, then maybe a Thread will work, but then you shouldn't be modifying the GUI from the new thread. And there are ways round that, but seeing as how you want the loop to run fast, have you tried not using a thread and getting the button to call the function directly? Commented Jan 19, 2021 at 17:26
  • Oh, I tried it and it makes the loop faster, but it still freezes the GUI and takes some time to highlight all the text. But I don't want that, as our app should not freeze suddenly when a user is working with it. Is there any way to shorten this time period? Commented Jan 19, 2021 at 17:31

1 Answer 1

0

I've been experimenting and this works faster:

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 widget\t\t"*500)

mainloop()
Sign up to request clarification or add additional context in comments.

1 Comment

pendantically speaking, 1.0 needs to be "1.0" - text indexes are strings, not floating point numbers. But yes, highlighting groups of characters will be much, much faster than doing one at a time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.