Python Forum
[Tkinter] Tk window not displaying until loop has completed - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [Tkinter] Tk window not displaying until loop has completed (/thread-34564.html)



Tk window not displaying until loop has completed - Ganga - Aug-09-2021

Hi, I'm new to python and Tkinter (as in two days in!), so appreciate this may be a pretty obvious mistake I'm making. Why is it that if I have a loop(s) in my code that the Tk window doesn't display until the loop(s) has gone through all it's iterations. What I want is for the window to display at the start so that I can then view the result of each iteration in the window. Here's a small sample program to show what I mean. If you run it yourself you'll see the lag before the window opens.

from tkinter import *

root = Tk()

for column in range (0, 50):
    
    for row in range (0, 40):
        
        #calculate next number from row and column
        number = row+(column*40)
        #create label
        myLabel = Label(root, text=str(number))
        #display label
        myLabel.grid(row=row, column=column)
    
root.mainloop()



RE: Tk window not displaying until loop has completed - deanhystad - Aug-09-2021

tkinter updates things when your program is idle. Normally this is what you want to happen. If you have something that takes a long time to complete you should break it up into smaller pieces of processing, or run it in a thread or parallel process. This way your GUI is still responsive to user actions.

You will not see anything before mainloop() is called. Here is a much longer delay with a lot less going on.
import tkinter as tk
import time

start = time.time()
root = tk.Tk()
tk.Label(root, text='Hello World!').pack()
print(time.time() - start)
time.sleep(5)
root.mainloop()
If you don't care about having a responsive interface, you can call update() to update your widgets.
import tkinter as tk
import time

start = time.time()
root = tk.Tk()
tk.Label(root, text='Hello World!').pack()
root.update()
print(time.time() - start)
time.sleep(5)
root.mainloop()
This draws the window right away, but the window is unresponsive and you get a busy cursor until the program wakes up from its 5 second nap.


RE: Tk window not displaying until loop has completed - Ganga - Aug-09-2021

OK. So, I added a root.update() inside the loops of my sample program which works to a point. It severely slows down the program though. Especially as it gets towards the end and there's more information to update. Isn't there a way to just update what is being added to the window, rather than updating the entire window every time through the loop?


RE: Tk window not displaying until loop has completed - deanhystad - Aug-09-2021

You shouldn't be using update at all. You shouldn't be writing programs that have a flow that requires something like update.

You can speed things up (make things less horrible) by updating less often. Maybe after 10 labels or 50 labels.


RE: Tk window not displaying until loop has completed - Ganga - Aug-09-2021

P.S. The ultimate goal is to have an image (or images) that smoothly move around inside the already existing window. In order to create the smoothness and reduce lag, I only want the image to be updated and not the entire window.


RE: Tk window not displaying until loop has completed - deanhystad - Aug-09-2021

I do not understand what you are trying to do. Your example is nothing like what you claim. Are you adding images or moving images, or are you changing images to give the impression of motion? What kind of program are you writing? What are these images? Why are they moving?

If you plan to move things with a loop you are going to have a problem. As I mentioned before, GUI programs are not supposed to wait. No long for loops. To allow any kind of interaction, your program will have to break the "moving image" into "moving image in baby steps" and periodically call a function to update the image position. In tkinter this is usually done using the after() function. Using after() you call a function every 50 milliseconds or so. The function moves your image, schedules itself to run again in 50 milliseconds (using after()), and returns. Now that mainloop() is not blocked from executing, changes made in the move function quickly appear in the window.


RE: Tk window not displaying until loop has completed - Ganga - Aug-09-2021

Hi, sorry for any confusion. The example was just to show that the window was not showing until after the loop had completed.

The program I am hoping to write is a simulation of ant foraging behaviour. Therefore, the images will be small bitmap ants. They are moving because, well, that's what ants do, especially when they are foraging.

What you suggest with the after() function sounds more like what I'm looking for.

Forgive my ignorance, I haven't done any programming since I was studying in the early 90's using Pascal. I will have to get my head around how the GUI's operate. Thank you for your patience.


RE: Tk window not displaying until loop has completed - deanhystad - Aug-09-2021

You might want to look at PyGame. It is designed for making games, and games often involve lots of moving images around.

If you want to use tkinter, you should look at canvas. You would still use .after(), but it is easier to move little bitmaps around on a canvas than it is in a frame.


RE: Tk window not displaying until loop has completed - Ganga - Aug-09-2021

Ok. There's some very useful pointers there. Thank you for your help.