Samuel
Samuel

Reputation: 49

Tk GUI Not Responding

Can someone help me on this situation? I am trying to make a GUI that is used for colors demo of all RGB matrix in the canvas. Unfortornately, the GUI is not responding and it doesn't change colors as expected until the loop is finished. Is there anything wrong? I often encounter this problem if I configure a widget in a loop.

package require Tk
package require math
proc changeColor {rM gM bM} {
    for {set r 0} {$r<=$rM} {incr r} {
        for {set g 0} {$g<=$gM} {incr g} {
            for {set b 0} {$b<=$bM} {incr b} {
                set rHex [format %02X $r]
                set gHex [format %02X $g]
                set bHex [format %02X $b]
                set mark #
                set color [append mark $rHex $gHex $bHex]
                .cv config -bg $color
                .lb config -text "[format %03d $r] [format %03d $g] [format %03d $b]"
                after 500
            }
        }
    }
}

canvas .cv
ttk::label .lb
ttk::button .bt -text Run -command {changeColor 255 255 255}

grid .cv -row 0 -column 0 -sticky news
grid .lb -row 1 -column 0 -sticky we
grid .bt -row 2 -column 0

Code_Snapshot

GUI_Snapshot

Upvotes: 1

Views: 384

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137577

Tk (and Tcl) processes no events at all during a synchronous after 500. It just stops the process for that 500 ms.

You need to instead process events for that time. Replace the after 500 with:

after 500 {set go_on yes}
vwait go_on

Be aware that the go_on there is global, and that this can cause problems with code-reentrancy. You'll want to disable the button that runs the procedure while your code is running.

Or you can use Tcl 8.6 and convert everything to be a coroutine. Then you'll be able to do an asynchronous sleep without danger of filling the stack:

proc changeColor {rM gM bM} {
    for {set r 0} {$r<=$rM} {incr r} {
        for {set g 0} {$g<=$gM} {incr g} {
            for {set b 0} {$b<=$bM} {incr b} {
                set rHex [format %02X $r]
                set gHex [format %02X $g]
                set bHex [format %02X $b]
                set mark #
                set color [append mark $rHex $gHex $bHex]
                .cv config -bg $color
                .lb config -text "[format %03d $r] [format %03d $g] [format %03d $b]"
                ####### Notice these two lines... ########
                after 500 [info coroutine]
                yield
            }
        }
    }
}

##### Also this one needs to be altered #####
ttk::button .bt -text Run -command {coroutine dochange changeColor 255 255 255}

# Nothing else needs to be altered

Upvotes: 2

Related Questions