[Tkinter-discuss] loop delay

Bryan Oakley bryan.oakley at gmail.com
Mon Oct 22 13:13:07 CEST 2012

On Sun, Oct 21, 2012 at 5:31 PM, Paul Simon <psimon at sonic.net> wrote:
> I' m a novice python programmer and now starting to learn tkinter for a
> front and db back end to replace an application written MS Access/VBA.  The
> following program doesn't work as I expected as data is not written to the
> text box until the def is exited.  If I include a print statement with the
> increment it is printed.
> Any suggestions are welcome.

The crux of the matter is this: the windows are (re)drawn in response
to events which instruct them to redraw themselves. The only way that
can happen is if the event loop is running.

When you have a loop in your code, while that loop is running the
event loop is _not_ running. This is especially bad if you put a sleep
in your code, because that causes the entire GUI to freeze. As a rule
of thumb you should never, ever use sleep in a GUI.

The quick fix for your problem is to add a call to `update_idletasks`
in your loop. Why `update_idletasks` instead of `update`? Because the
redrawing of windows is considered an "idle" task -- it is a class of
event that Tk will service when it is otherwise idle. That, and
calling `update` is potentially dangerous since it effectively creates
a new event loop nested inside the current event loop.

However, that's just a hack. The better solution is to architect your
code differently. If you have a long running process you should
consider running it in a separate thread or separate process. Even
better, if you can divide your work up into small chunks you can set
it up so that each chunk can be run during one iteration of the event
loop. You can request that Tkinter execute something during a future
iteration of the event loop with the `after` method.

Typically you do this with a function that does one chunk of work. It
then checks to see if there are any more chunks (by checking a flag,
or a list of data to be processed, etc) . If it finds there is more
work to do it uses itself as an argument to `after`, with a delay of a
few ms. That way, each time the event loop loops, it does one chunk of
your processing. No threads, no processes, no sleeps.

If you want to see an example of a countdown timer using this
technique see http://stackoverflow.com/a/10599462/7432

More information about the Tkinter-discuss mailing list