Light weight widgets that are drawn on a canvas, rather than having their own window, might be useful in several situations.
Kevin Kenny made some nice
canvas buttons.
I took Kevin's buttons and added a 3-D appearance. Kevin's file, slightly altered, appears here.
The 3-D effect is achieved using routines from the 3-D Boxes (Support for Canvas Buttons in 3-D) page.
Those routines allow you treat corners and sides separately, so if someone wanted to make a
combobox, they could. It's not restricted to boxes, and it's not restricted to buttons.
Here's a link to the support routines, that these 3-D canvas buttons are built on.
3-D Boxes (Support for Canvas Buttons in 3-D)Here's a link to the original Canvas Buttons.
Canvas Buttons Rick Hedin
set ::RCSID([info script]) \
{$Id: 1379,v 1.3 2006-09-24 06:00:02 jcw Exp $}
package provide canvasbutton 1.0
source box3d.tcl
namespace eval canvasbutton {
variable nexttag 0
variable command
variable cursor
variable enteredButton {}
variable pressedButton {}
variable buttoninfo
namespace export canvasbutton
}
proc canvasbutton::canvasbutton {w x0 y0 x1 y1 text cmd} {
variable nexttag
variable command
variable buttoninfo
set btag [list canvasb# [incr nexttag]]
set command($btag) $cmd
$w create rectangle [expr $x0 - 2] [expr $y0 - 2] [expr $x1 + 2] \
[expr $y1 + 2] -outline black -width 3 -state hidden \
-tags [list $btag [linsert $btag end frame] ]
set id [Create3DBox $w $x0 $y0 $x1 $y1 5 -dx dx -dy dy \
-tags [list $btag [linsert $btag end button] ] ]
set buttoninfo($nexttag,id) $id
set x [expr { ($x0+$x1) / 2 }]
set y [expr { ($y0+$y1) / 2 }]
set buttoninfo($nexttag,textx) $x
set buttoninfo($nexttag,texty) $y
$w create text [expr $x + $dx] [expr $y + $dx] -anchor center \
-justify center -text $text \
-tags [list $btag [linsert $btag end text]]
set extent [Get3DBoxPolygon $id]
$w create polygon $extent -fill "" -outline "" \
-tags [list canvasb $btag [linsert $btag end region] ]
$w bind canvasb <Enter> [list [namespace current]::enter %W]
$w bind canvasb <Leave> [list [namespace current]::leave %W]
$w bind canvasb <ButtonPress-1> \
[list [namespace current]::press %W]
$w bind canvasb <ButtonRelease-1> \
[list [namespace current]::release %W]
return $btag
}
proc canvasbutton::enter {w} {
variable enteredButton
variable pressedButton
variable buttoninfo
variable cursor
set enteredButton [findBtag $w]
set frame [linsert $enteredButton end frame]
set button [linsert $enteredButton end button]
set text [linsert $enteredButton end text]
set cursor($w) [$w cget -cursor]
$w configure -cursor arrow
$w itemconfigure $frame -state normal
$w lower $frame $button
if {![string compare $enteredButton $pressedButton]} {
set id [lindex $enteredButton 1]
Set3DBoxRelief $buttoninfo($id,id) recessed -dx dx -dy dy
$w coords $text [expr $buttoninfo($id,textx) + $dx] \
[expr $buttoninfo($id,texty) + $dy]
}
}
proc canvasbutton::leave {w} {
variable enteredButton
variable pressedButton
variable buttoninfo
variable cursor
if {[string compare $enteredButton {}]} {
set btag [findBtag $w]
set frame [linsert $btag end frame]
set text [linsert $btag end text]
$w itemconfigure $frame -state hidden
$w configure -cursor $cursor($w)
unset cursor($w)
if {![string compare $btag $pressedButton]} {
set id [lindex $btag 1]
Set3DBoxRelief $buttoninfo($id,id) raised -dx dx -dy dy
$w coords $text [expr $buttoninfo($id,textx) + $dx] \
[expr $buttoninfo($id,texty) + $dy]
}
set enteredButton {}
}
return
}
proc canvasbutton::press {w} {
variable pressedButton
variable buttoninfo
set pressedButton [findBtag $w]
set text [linsert $pressedButton end text]
set id [lindex $pressedButton 1]
Set3DBoxRelief $buttoninfo($id,id) recessed -dx dx -dy dy
$w coords $text [expr $buttoninfo($id,textx) + $dx] \
[expr $buttoninfo($id,texty) + $dy]
return
}
proc canvasbutton::release {w} {
variable enteredButton
variable pressedButton
variable buttoninfo
variable command
set pressedButtonWas $pressedButton
set pressedButton {}
set text [linsert $pressedButtonWas end text]
set id [lindex $pressedButtonWas 1]
Set3DBoxRelief $buttoninfo($id,id) raised -dx dx -dy dy
$w coords $text [expr $buttoninfo($id,textx) + $dx] \
[expr $buttoninfo($id,texty) + $dy]
if {![string compare $enteredButton $pressedButtonWas]} {
uplevel #0 $command($pressedButtonWas)
}
return
}
proc canvasbutton::findBtag {w} {
foreach tag [$w itemcget current -tags] {
if {[regexp {^canvasb#} [lindex $tag 0]]} {
return [lrange $tag 0 1]
}
}
return {}
}
if {![string compare $argv0 [info script]]} {
grid [canvas .c -width 300 -height 200 -cursor crosshair]
namespace import canvasbutton::*
.c create text 150 150 -anchor n -tags label \
-font {Helvetica 10 bold}
canvasbutton .c 30 70 80 120 "First\nButton" {
.c itemconfigure label -text One
}
canvasbutton .c 125 70 175 120 "Second\nButton" {
.c itemconfigure label -text Two
}
canvasbutton .c 220 70 270 120 "Third\nButton" {
.c itemconfigure label -text Three
}
canvasbutton .c 240 160 280 180 "Quit" exit
}