proc every {ms body} { global everyId if {$ms eq "cancel"} { if {[info exists everyId($body)]} { after cancel $everyId($body) unset everyId($body) } } else { if {[info exists everyId($body)]} { # This makes sure there is only 1 every for this body after cancel $everyId($body) } set everyId($body) [after $ms [info level 0]] uplevel #0 $body } }The second snippet, "Update," was provided by Pat Thoyts, also on the Tile developer's list, sets up the numerical logic for the progress widget:
proc Update {w interval} { #global w interval set v [expr {[$w get] + $interval}] if {$v > [$w cget -to]} { set v [$w cget -from] } $w set $v }The third snippet, "reset," sets up the "after cancel" call to close the progress bar loop:
proc reset {} { foreach id [after info] {after cancel $id} }And finally, I put all these procedures and call them from this "Show Progress" procedure, developed with assistance from Pat Thoyts, which can then be called from a menu or button command:
proc ShowProgress {} { toplevel .progress tbutton .progress.button -width 10 -text close -command "reset; destroy .progress" -highlightbackground gray97 pack .progress.button -side right -fill x tlabel .progress.text -textvariable show pack .progress.text -side top -fill both pack [tprogress .progress.show -from 0 -to 10] -fill both -side bottom .progress.show set 0 grab .progress wm title .progress "TkDarwinPorts Progress" every 250 {Update .progress.show 1} }One caveat: it doesn't seem possible to directly tie this indeterminate progressbar to the execution of a specific procedure within the Tk event loop--i.e., call the ShowProgress procedure and then terminate it when the parent procedure has closed. When I tried that, the progressbar loop would go on and on even after the parent procedure had finished. Setting up the second top-level window with the progressbar and then calling "reset," and then destroying the window with the "close" button, is the most effective solution. While it doesn't exit on the closure of the parent procedure, it is cleanly terminated when the end user clicks on the button.
MAK (19 Feb 2005) - Actual barber poles ought to be possible with patch [1], which implements phased progress bar support. With patch the Aqua progress bar still looks the same but you get the "moving bubbles" effect that you often see in other applications. I suspect you could do your own progress bar theme with a phased barber pole graphic, and then not have to do anything to keep it animated beyond choosing the right phase graphic to display when told to. (Though, it might have to be a theme in C.)