Updated 2016-01-14 07:09:35 by pooryorick

checkbutton, a Tk command, creates and manipulates checkbutton widgets.

See Also  edit

Boolean Checkbutton
Accept any boolean value.
ttk::checkbutton
a ttk themed theckbutton
checkbox
a type of widget composed of checkbuttons
Lightbutton
a pure Tcl package mimicking the radio and the checkbuttons, with bright and pretty colors.
checkvar
for a bunch of checkbuttons to represent a variable

Documentation  edit

official reference
TIP 109, New Look for Checkbutton and Radiobutton on Unix
included as of Tcl 8.5
TIP 110
describes tri-state options, which are included as of Tcl 8.5

Description  edit

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:
-variable
... Specifies the name of a global variable to set to indicate whether or not this button is selected. Defaults to the name of the button within its parent (i.e. the last element of the button window's path name).

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.