Home > Back-end >  tkinter ScrolledText waits for loop to stop when there is a sleep command but updates live when ther
tkinter ScrolledText waits for loop to stop when there is a sleep command but updates live when ther

Time:08-19

I am trying to output live stdout and stderr to a ScrolledText widget. I have gotten the live output fine, but the ScrolledText widget is not updating until the script is finally executed. I tested this on a simpler example to see if it was the time in between stdout lines. I insert a time.sleep(1) call before I insert the text to the ScrollText widget. Can someone explain to me why the ScrolledText widget doesn't update after every scroll_object.insert(tk.INSERT,string) call?

import tkinter as tk
from tkinter.scrolledtext import ScrolledText
import time

def insert_stuff(scroll_object):
    for i in range(10):
        time.sleep(1)
        string = f'{i}\n'
        scroll_object.insert(tk.INSERT,string)


root = tk.Tk()
output = ScrolledText(root)

button = tk.Button(window,text='Insert Text', command = lambda: insert_stuff(output))

output.pack()
button.pack()

window.mainloop()

CodePudding user response:

As Bryan Oakley pointed out "sleep" halts the entire programm for the specified amount of time.

But if I understand you correctly, you are trying to update the ScrolledText widget, every time a sleep call (or a subprocess poll) is completed.

If so, just try to add this to your code:

scroll_object.update()

So your function looks like this:

def insert_stuff(scroll_object):
    for i in range(10):
        time.sleep(1)
        string = f'{i}\n'
        scroll_object.insert(tk.INSERT,string)
        scroll_object.update()

In tkinter it basically works this way (in the order of your code being executed):

  1. The code you wrote runs through
  2. Once the mainloop is reached, you are able to interact with the window
  3. Once a function is called (like then you press the "Insert Text" button) the code you wrote for that function is executed (including the sleep statement). But within that time, no other code is executed. Therefore not even the tkinter code which updates the ScrolledText widget to show the new entries. With the .update() function call, you manually refresh the widgets state (this works for all sorts of tkinter widgets)!

Hope this helps :)

EDIT: As Delrius Euphoria pointed out, the window will still be frozen (depending on how long your subprocess poll takes in terms of time). To prevent this freezing from happing you have multiple options:

  1. Try using an async function
  2. Use multiprocessing module and a Process
  3. Use multiprocessing module and a Pool

All three options are too complicated to explain here, but I suggest you to try your luck with option 2. Just go ahead and look it up on the internet. Long story short it basically helps you to outsource a certain task (= function) to another thread of your cpu.

  • Related