Skip to content
Advertisement

How to develop dialog gauge in tcl / tk that gets loop value and updates in scale widget by moving it

I’m trying to make a progress bar dialog like GNU/Linux Xdialog –gauge

Apparently you should get a value, which is updated for ‘one second’, from time to time.

This increment is done through a for loop already pre-configured to give the progressive count.

From my tests I did, and how far my knowledge of tcl/tk could go is like this:

proc bar { pos } {
global txt
set txt $pos
}

set btn [button .btn -text "Play" -relief groove -command { bar $pos }]

scale .scl -length 200 -width 5 -orient horizontal -from 0 -to 100 -resolution 1 -variable value -sliderlength 5 -sliderrelief flat -activebackground blue -command { bar } -showvalue 0

label .lbl -textvariable txt -width 5

grid $btn -row 0 -column 0
grid .scl -row 0 -column 1
grid .lbl -row 0 -column 2

global value
for {set value 0} {$value < 10} {incr value} {  
after 1000; # delay
if {$value < 10} { puts "Number: $value" }
bind . "$btn invoke"
}

This works, so in the console .. it does not show the form, window with the scale widget being slowly moved. So I need help from the most experienced how can I get this?

I created a multi-frame animation to get a better idea. Look:

enter image description here

Advertisement

Answer

The command

after 1000; # delay

just blocks and does not allow Tcl/Tk to do any processing. Since your program has not yet entered the event loop, nothing will be displayed.

In some cases, whatever code that ends up replacing the ‘after’ command will have delays that will allow screen updates.

# don't put the bind inside the for loop
# is this even needed?
bind . "$btn invoke"

set ::waitvar 0
for {set value 0} {$value < 10} {incr value} {  
   # a simplistic solution for purposes of this example
   # vwait cannot be nested, and should be used very carefully or not at all.
   after 1000 set ::waitvar 1
   vwait ::waitvar
   set ::waitvar 0
}

A better method will be something more like:

  proc updateScale { v } {
     global value
     set value $v
  }

  proc checkProgress { } {
     # query the progress of the task and see how far along it is
     set progress [queryProgress]
     updateScale $progress
     after 1000 [list checkProgress]
  }

  # schedule a call to checkProgress to start things off.
  after 1000 [list checkProgress]
  # and now the program enters the event loop
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement