spinbox

Difference between version 33 and 34 - Previous - Next
A '''spinbox''' is a specialized `[entry]` widget that allows
iterating through a sequence of available values, typically using an up-arrow
and a down-arrow.  


** Documentation **

    :   http://www.tcl.tk/man/tcl/TkCmd/spinbox.htm


** Example **


======
package require Tk 8.4

set ::var 0.75
proc myproc { } {
    puts "myproc: $::var"
}

spinbox .spin -from 0.00 -to 5.00 -increment 0.25 -format %5.2f -width 10 \
    -font 10 -justify center -textvariable var -command myproc

pack .spin
======


** The '''`-format`''' Option **

[[Explain not-well-documented-or-intuitive-to-many importance of -format in
example:]]

======
spinbox .s2 -from 0.0 -to 15.875 -increment 0.125 \
    -format %1.3f
======

** The '''`-command`''' Option **

This would be a good place for an explanation of the `-command` option and
editing the spinbox's entry.  And possible workarounds.  It is completely
non-intuitive and causes a lot of lost time.

[DRF]:  I use a `[bind]` to get around the editing of the entry problem:

======
bind .spin <Leave> { puts [%W get] }
======

However, it would be nice to be able to execute the `-command` from within
`[bind]`.




** Implementing Spinbox in Earlier Versions of Tk ** 


Here is a concoction of a 1-line high listbox with two tiny buttons, to
approximate the effects of a spinbox:

======
#! /bin/env tclsh

package require Tk

proc spinner {w args} {    

    set im(up) [image create bitmap -data {
                #define i_width 5
                #define i_height 3
                static char i_bits[] = {
                        4,14,31
                }}
        ]

    set im(dn) [image create bitmap -data {
                #define i_width 5
                #define i_height 3
                static char i_bits[] = { 31,14,4 }}
        ]

    frame $w
    eval listbox $w.l -height 1 $args    
    frame $w.f
    button $w.f.1 -image $im(up) -width 10 -height 4 \
        -command [list $w.l yview scroll -1 unit]
    button $w.f.2 -image $im(dn) -width 10 -height 4 \
        -command [list $w.l yview scroll 1 unit]
    pack $w.f.1 $w.f.2
    pack $w.l $w.f -side left -fill y
    return $w.l
} ;# RS
======

Example:

======
set testlist {foo bar grill room}
spinner .x -listvar testlist -bg yellow
pack .x
======

Result: [WikiDbImage spinner.jpg]

Should you wonder how I got these little arrow images - then it's time for a
little plug for [strimj - string image routines], where the command

======
strimj::xbm "@@@@@\n @@@ \n  @ "
======

delivers the XBM code for the down arrow (and the order of rows needed only to
be reverted for the up arrow).

----

Still, the XBM specification looks ugly as sin (and disturbs indentation).
Here's a little wrapper that hides the boring parts:

======
proc xbmdata {width bytes} {
    set bytesperline [expr {($width+7) / 8}]
    set nbytes [llength [split $bytes ,]]
    set height [expr {$nbytes / $bytesperline}]
    set res    "#define i_width $width\n"
    append res "#define i_height $height\n"
    append res "static char i_bits[] = {\n$bytes}"
} ;# RS
======

and in the ''spinner'' code you just write:

======
set im(up) [image create bitmap -data [xbmdata 5 4,14,31]]
set im(dn) [image create bitmap -data [xbmdata 5 31,14,4]]
======

[LV]: I'd really encourage people to place code that allows older versions of
Tcl/Tk to have ''forward compatible'' functionality into tcllib and tklib -
that way everyone benefits.  Appropriate package info should keep it from
kicking in inappropriately.

[RS]: Mmh, yeah, but that would involve "real" work (to fulfill the spinbox
spec as much as possible), while I just quickly hacked this together in
response to a c.l.t. post

[LV]: That's fine - if you notice, I'm not talking merely about the following
code - I know that there has been work elsewhere on the wiki on ''forward
compatibility''; moving this type of code off of the wiki and into tcllib or
tklib would enable more people to make use of it.



** Hex Spinbox **

[sbron]:  Until FRQ#1096323 is available the following code can be used to make
a hexadecimal spinbox:

======
# Command procedure for making a hexadecimal spinbox
proc spinhex {w value direction format} {
    # Try to get the current hex value of the spinbox
    if {[scan $value %x newvalue] != 1} {set newvalue 0}

    # Calculate the new value
    if {$direction eq "up"} {
        if {$newvalue < round([$w cget -to])} {
            incr newvalue
        } elseif {[string is true [$w cget -wrap]]} {
            set newvalue [expr {round([$w cget -from])}]
        }
    } elseif {$direction eq "down"} {
        if {$newvalue > round([$w cget -from])} {
            incr newvalue -1
        } elseif {[string is true [$w cget -wrap]]} {
            set newvalue [expr {round([$w cget -to])}]
        }
    }

    # Set the spinbox to the new value
    $w set [format $format $newvalue]
}

# Create the spinbox. Set increment to 0 to disable the builtin button actions
spinbox .spin -width 6 -from 0 -to 65535 -increment 0 -wrap true \
    -command {spinhex %W %s %d %%04X}

# Initialize the spinbox value
spinhex .spin 0 start %04X
======

[AMG]: Is `[string is] true` redundant in this context?

** Control with Mouse Wheel **

[ET]: Since TK 8.6.0, the mouse wheel does not require focus, but instead sends it's input to whatever widget it is over when you twirl the wheel. This makes it especially nice for adjusting a set of spinboxes. And it works equally well for numbers with -from -to and a list of -values.
Unfortunately, tThis simple method is not needed for ttk::spinbox since it has nMouseWheel binvokedings mebuilthod in.

======tcl
proc adjust {spinner value} {
    if { $value > 0 } {
        $spinner invoke buttonup
    } else {
        $spinner invoke buttondown
    }
}

spinbox .spin1  -from 20 -to 300  -increment 10
spinbox .spin2  -from 1 -to 50    -increment 1
spinbox .spin3  -values {one two three four five}

bind .spin1 <MouseWheel> {adjust %W  %D}
bind .spin2 <MouseWheel> {adjust %W  %D}
bind .spin3 <MouseWheel> {adjust %W  %D}

pack .spin1 .spin2 .spin3
======


** See Also **

    :   [spinbox menubutton]
    :   [ttk::spinbox]
    :   [timebox], a specialized spinbox


<<categories>> Widget | Command | GUI | Tk syntax help | Arts and Crafts of Tcl-Tk Programming