Reputation: 177
I am trying to update text in a scrolltext widget within a for loop. The print statement shows the updated text each time through the loop but the I don't see anything in the Tk window until the loop has completed. Then I see '('This is ', 4, ' times though the loop.')'. I never see 0 through 3 being displayed.
from tkinter import *
from tkinter import scrolledtext
import time
main = Tk()
main.title("test_loop")
main.geometry('750x625')
main.configure(background='ivory3')
def show_msg():
global texw
textw = scrolledtext.ScrolledText(main,width=40,height=25)
textw.grid(column=0, row=1,sticky=N+S+E+W)
textw.config(background="light grey", foreground="black",
font='arial 20 bold', wrap='word', relief="sunken", bd=5)
for i in range(5):
txt = "This is ", i, " times though the loop."
txt = str(txt)
print(txt)
textw.delete('1.0', END) # Delete any old text on the screen
textw.update() # Clear the screen.
textw.insert(END, txt) # Write the new data to the screen
time.sleep(5)
btn = Button(main, text = 'display_log', bg='light grey', width = 15,
font='arial 12', relief="raised",bd=5,command = show_msg)
btn = btn.grid(row = 0, column = 0)
main.mainloop()
Upvotes: 0
Views: 5683
Reputation: 1390
The problem is that your window is not getting updated until the loop is running. To avoid it 'freezing', you should update it periodically. Do something like this:
from tkinter import *
do_your_init()
tk = Tk()
do_your_preparation()
for x in range(n):
do_your_update()
tk.update()
Hope that's helpful! Good luck!
Upvotes: 5
Reputation: 15226
First lets clean up the code to be more PEP8 friendly and also change import so we are not importing *
. By importing *
you run the risk of overwriting imports and built in methods.
I would create your widget outside of your function and then replace your loop containing sleep()
with a function that can call itself and uses after()
as sleep will block your mainloop rendering your GUI useless and frozen until all the sleeping has completed. after()
is used to avoid this problem.
import tkinter as tk
from tkinter import scrolledtext
root = tk.Tk()
root.title('test_loop')
root.geometry('750x625')
root.configure(background='ivory3')
textw = scrolledtext.ScrolledText(root, width=40, height=25)
textw.grid(column=0, row=1, sticky='nsew')
textw.config(background='light grey', foreground='black', font='arial 20 bold', wrap='word', relief='sunken', bd=5)
def show_msg(count=None):
if count is not None:
if count <= 5:
txt = 'This is {} times though the loop.'.format(count)
textw.delete('1.0', 'end')
textw.insert('end', txt)
count += 1
root.after(2000, lambda: show_msg(count))
else:
show_msg(1)
tk.Button(root, text='display_log', bg='light grey', width=15, font='arial 12', relief='raised', bd=5,
command=show_msg).grid(row=0, column=0)
root.mainloop()
Results:
If you want to keep all your logs on the screen (assuming you want to as normally logs should all be kept) I would remove the delete command and then add a \n
to the text so each log is on a new line.
Simply edit the function like this:
def show_msg(count=None):
if count is not None:
if count <= 5:
txt = 'This is {} times though the loop.\n'.format(count)
# textw.delete('1.0', 'end')
textw.insert('end', txt)
count += 1
root.after(2000, lambda: show_msg(count))
else:
show_msg(1)
Results:
Let me know if you have any questions.
Upvotes: 4
Reputation: 385800
You are sleeping after inserting the text, and then deleting the text before the next time you call update
. The call to update
needs to happen after inserting the text, not before.
Upvotes: 1