Update Idletasks - Another TCL "Ahh hah" moment


Have you ever opened a WISH shell and run a script doing a long calculation with embedded put statements to display intermediate results? Ever scratched your head when you wait for a while then get the last few results output to the display in that scenario?

Try this in both WISH and TCLSH shell windows:

for {set i 0} {$i < 10000} {incr i} {
  puts $i
}

Notice the difference now? In the TCLSH you get a continuous stream of output. In the WISH shell only the last few appear after the calculation is completely finished. (If you scroll back you see everything -- just not as it was happening.)

This behavior has confused me for a long time. But I recently discovered the solution: use the TCL update command.

The update command was part of TK until the event loop (being such a useful thing) was moved from TK into TCL in the Tcl 7.5/Tk 4.1 release.

Display updates only occur after all other events have been processed in the event loop. This is significant because the WISH shell is a Tk window (subject to the event loop) while the TCLSH window is just an operating system window.

The script above prevents entry into the event loop so it never gets to the point where it can respond to display update events. The solution?

Those clever Tcl architects created the update command for this purpose. It forces entry into the event loop where events can be processed (in particular the ones that force the display to change.) Try this:

for {set i 0} {$i < 10000} {incr i} {
  puts $i
  if {$i % 1000 == 0} {update idletasks}
}

Running this in WISH will yield ten updates. You will not see anything different in the TCLSH window.

Of course there may be some speed advantage in NOT updating the display but typically, with put statements anyway, you want to see them as you run the script.

Another typical use involves a Tk application where you need to be able to stop a calculation in progress. If you have a button for this (which sets a variable to some "stop" value) then you could poll the variable during your algorithm at good stopping points. However, your script will never see the variable change because the button click event won't be seen! Your script needs the update command. However, in this case you want just the naked update command with no idletasks option.

The naked update command ensures that all events are processed by the event loop -- not just the ones handled during idle time. So it permits the processing of buttons, key-presses, and all the other possible events.

Copyright Ā© 2009 Aspen Logic, Inc. All Rights Reserved.