checkbutton , a Tk command, creates and manipulates checkbutton widgets.
Could someone provide some examples of how to use and manipulate this?
To avoid the dangers of creative writing, always use the -variable option.
[email protected] wrote in comp.lang.tcl:
I would like to be able to control the location of the box in checkbutton and make it appear to the right of it's [sic] text (rather than to the left -- as is the default). Is this possible?
You can approximate it with a little wrapper that places a label left of a text-less checkbutton. Quick shot:
proc lcheckbutton {w args} { array set opt {-text {}} array set opt $args frame $w -bg red label $w.1 -text $opt(-text) unset opt(-text) eval [list checkbutton $w.2 -text {}] [array get opt] pack $w.2 $w.1 -side right -fill x set w } ;# RS #--------------------------------------- testing: checkbutton .1 -text Right lcheckbutton .2 -text Left eval pack [winfo children .] -anchor w
To fully emulate the checkbutton protocol, some more work is of course needed...
Instead of work, here's more play: the vertical command places the text of a radio- or checkbutton below the clickable field:
proc vertical {type w args} { frame $w set pos [lsearch $args -text] if {$pos == -1} { set text {} } else { set text [lindex $args [expr $pos+1]] set args [lreplace $args $pos [incr pos]] } $type $w.r {*}$args [list -text {}] -pady 0 label $w.t -text $text -pady 0 pack $w.r $w.t -side top -pady 0 -padx 0 -fill x -anchor e set w } ;# RS vertical radiobutton .io.ri$i -text X$i -variable Xary($i)
Here's a procedure which does all the nessecary stuff to bind label and checkbutton - when label is of left as separate control and checkbox is textless. All mouse interactions are taken care of - on_mouseover, etc:
proc setWidgetsState {state widgets} { foreach widg $widgets {$widg configure -state $state} } ; # SetWidgetsState proc bindLabelToCheckbutton {lbl chkBtn} { foreach prop {-activebackground -activeforeground} { $lbl configure $prop [$chkBtn cget $prop] } bind $lbl <Enter> [list setWidgetsState active [list $lbl $chkBtn]] bind $lbl <Leave> [list setWidgetsState normal [list $lbl $chkBtn]] bind $chkBtn <Enter> +[list setWidgetsState active $lbl] bind $chkBtn <Leave> +[list setWidgetsState normal $lbl] bind $lbl <1> [list $chkBtn invoke] } ; #bindLabelToCheckbutton
Just add the following call to lcheckbutton (above) and you are all done:
bindLabelToCheckbutton $w.1 $w.2
Lars H 2007-06-06:
Yesterday I needed a window that displayed a set of images and let the user select a subset of them. Noticing that checkbutton has a -image option, I thought "Great, I'll just create a grid of checkbuttons and display the images in these!" Slightly simplified, the code for setting this up looked like this:
for {set n 1} {$n < $limit} {incr n} { grid [ checkbutton $t.back.i${n} -compound top -text $Info($n) \ -image $im($n) -variable $t.back.i${n} \ -justify left -wraplength [image width $im($n)] ] -row $n -column 1 }
Unfortunately, this didn't look so good -- for some reason the checkbuttons ended up being twice as wide as the image, which occupied the right half of the widget. The left half was empty, except for the actual checkbox which was about its normal distance from the left edge of the widget; in other words the box was very far from the image and text.
For now, I'll try putting the image in a separate label widget instead, but the checkbutton behaviour seems baroque. Does anyone know why this happens? (Just so you know, this is with aqua as tk windowingsystem.)
WJP 2007-09-08:
I'm not sure why the layout is as it is, but I tried this with -indicatoron 0, that is, without the checkbox, and thought it looked pretty nice (in X11/Linux). Do you really need the checkbox?
Here is a gotcha which might surprise:
pack [checkbutton .cb -text {test button} -bg blue -fg white]
The checkmark seems to disappear whenever you release the mouse button (under Windows at least). This is because the text colour is the same as the background of the checkbox. Use:
pack [checkbutton .cb2 -text {Good button} -bg blue -fg white -selectcolor gray]
You should choose a suitable selectcolor to contrast with the textcolor.
nibbler 2011-08-02: Possible bug in the handling of checkbox states. With the code below, I'd expect every checkbutton in every window to be unique, however, the first two in each window share states, despite having different parent paths:
package require Tk proc CreateRootWindow {} {; ## Create the root window ## Create the window wm title . {Tk checkbutton bug test} wm minsize . 300 75 ## Create some buttons to open the child windows button .button1 -text {Open window one} -width 15 -state normal -command [ list CreateWindow 1] button .button2 -text {Open window two} -width 15 -state normal -command [ list CreateWindow 2] button .button3 -text {Open window three} -width 15 -state normal -command [ list CreateWindow 3] ## Pack everything pack .button1 .button2 .button3 } proc CreateWindow index {; ## Create the child windows # Destroy any existing instance of the window if it exists catch {destroy .window$index} set blah$index 0 # Create the window toplevel .window$index wm title .window$index "Window $index" wm minsize .window$index 200 100 # Create the two buggy checkbuttons checkbutton .window$index.check1 label .window$index.label1 \ -text "Checkbutton one with unique parent (.window$index.check1)" checkbutton .window$index.check2 label .window$index.label2 \ -text "Checkbutton two with unique parent (.window$index.check2)" # Create a checkbutton that isn't buggy thanks to its -variable option checkbutton .window$index.check3 -variable blah$index label .window$index.label3 \ -text "Checkbutton with unique variable (.window$index.check3)" # Create the unique checkbutton checkbutton .window$index.unique$index label .window$index.label4 \ -text "Checkbutton with unique name (.window$index.unique$index)" # Pack everything pack .window$index.label1 .window$index.check1 .window$index.label2 \ .window$index.check2 .window$index.label3 .window$index.check3 \ .window$index.label4 .window$index.unique$index } CreateRootWindow; ## Begin
Tested with ActiveState Tcl/Tk 8.6 on Windows XP (x86, SP3) and Tcl/Tk 8.4 on Debian 6.0.2. Is this the behaviour you would expect?
If you use the -command option on the first two checkbuttons with different commands, this bug still exists, which makes this a pain if you want to bind a series of checkbuttons to commands in multiple windows.
RLE 2011-08-03: You have found documented behavior. Note from the checkbutton man page:
Your "first" buttons are named ".window$index.check1", so the "last element of the button window's path name" is "check1" for both. By omitting the -variable configuration setting, both buttons default to using the the same global variable "check1". Which is why they share state.