The following problems are frequently reported by users writing Tcl/Tk programs and are easy to correct with a little guidance. This section is not meant to be a complete guide to writing Tcl/Tk, but serves to address a few common situations.
Many Tk widgets allow you to tie a widget to a Tcl variable so that changes to either the widget or variable are mirrored in the other. This handy feature makes widget data instantly available in Tcl code, without the need to access the widget command:
label .tot_rev-text 0-textvariable totalRevenue set totalRevenue 263124 ;# updates widget also
The most common problem when using -variable and -textvariable options is forgetting that the variables the options name are referenced as global variables. If you create widgets inside of a procedure and then access the widget’s variable, be sure to define the variable as global.
proc mk_totRev {} { label .tot_rev -text 0 -textvariable totalRevenue pack .tot_rev global totalRevenue set totalRevenue 23128 }
Tk widgets (particularly buttons) often let you specify code to be run when the widget is selected. This code is known as a callback. You should put the code in braces, not quotes, to prevent variables from being interpreted until the user selects the widget. This is illustrated in the following example:
set count 0 button .b -text "Increment" -command {puts $count; incr count} pack .b
Callback scripts can be of any length, but long scripts tend to get unwieldy when included in the -command argument. It is often easier to define your callback script as a procedure and call that procedure in the callback:
proc CallBack {} { global count puts "Current value is: $count" incr count } set count 0 button .b -text "Increment" -command CallBack pack .b
A Tk application runs as an event-driven program. When your program starts, your code builds widgets and defines callbacks until Tcl reaches the “end” of your code. At this point, Tcl has entered an event loop in which user events are processed, calling the callback scripts that you defined as -command options for widgets and bind commands. The interface is active during event processing, and updates screen widgets accordingly.
If any of your callback scripts perform a significant amount of processing, the inter face will appear to be frozen while scripts are executing. One way to prevent a frozen interface is to periodically execute the update command, which allows events to be processed. If your intent is to allow widgets to be updated without accepting new user events, use the idletasks option. In the following example, the update command allows the label widget to update the screen. Without update, the program will appear frozen.
label .l -text "" proc count {} { for {set c 1; .l configure -text 0} {$c <= 5} {incr c} { update after 1000 .l configure -text $c } } button .b -text "count to five" -command count pack .l .b
If your program reads and writes to sockets, or via pipes to another program, consider using file events to keep your interface active. Reading from any channel will cause the Tcl interpreter to wait until data is ready before returning. Tcl’s fileevent command provides callback processing for files and sockets.