1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
|
# ----------------------------------------------------------------------
#
# cbutton.tcl --
#
# Example of how to provide button-like behavior on canvas
# items. (Posted on comp.lang.tcl by Kevin Kenny)
#
# source: https://wiki.tcl-lang.org/page/Canvas+Buttons
set ::RCSID([info script]) \
{$Id: 1383,v 1.3 2006-09-24 06:00:06 jcw Exp $}
package provide canvasbutton 1.0
namespace eval canvasbutton {
# nexttag - Next unique tag number for a "button" being
# created
variable nexttag 0
# command - command(tag#) contains the command to execute when
# a "button" is selected.
variable command
# cursor - cursor(pathName) contains the (saved) cursor
# symbol of the widget when the pointer is in
# a "button"
variable cursor
# enteredButton - contains the tag number of the button
# containing the pointer.
variable enteredButton {}
# pressedButton - contains the tag number of the "button"
# in which the mouse button was pressed
variable pressedButton {}
namespace export canvasbutton
}
# ----------------------------------------------------------------------
#
# canvasbutton::canvasbutton --
#
# Create a button-like object on a canvas.
#
# Parameters:
# w Path name of the canvas
# x0 Canvas X co-ordinate of left edge
# y0 Canvas Y co-ordinate of top edge
# x1 Canvas X co-ordinate of right edge
# y1 Canvas Y co-ordinate of bottom edge
# text Text to display in the button
# cmd Command to execute when the button is selected.
#
# Results:
# Unique canvas tag assigned to the items that make
# up the button.
#
# Side effects:
# A rectangle and a text item are created in the canvas,
# and bindings are established to give them button-like
# behavior.
#
#----------------------------------------------------------------------
proc canvasbutton::canvasbutton {w x0 y0 wd h text cmd state} {
variable nexttag
variable command
set btag [list canvasb# [incr nexttag]]
set command($btag) $cmd
set x [expr { $x0 + ($wd / 2) }]
set y [expr { $y0 + ($h / 2) + 1}]
if {$state} {
$w create rectangle $x0 $y0 [expr {$x0 + $wd}] [expr {$y0 + $h}] \
-fill lightgray -outline black -width 1 \
-tags [list canvasb $btag [linsert $btag end frame]]
$w create text $x $y -anchor center -justify center \
-text $text \
-tags [list canvasb $btag [linsert $btag end text]]
$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]
} else {
$w create rectangle $x0 $y0 [expr {$x0 + $wd}] [expr {$y0 + $h}] \
-fill lightgray -outline grey65 -width 1
$w create text $x $y -anchor center -justify center \
-text $text -fill grey65
}
return $btag
}
# ----------------------------------------------------------------------
#
# canvasbutton::enter --
#
# Process the <Enter> event on a canvas-button.
#
# Parameters:
# w Path name of the canvas
#
# Results:
# None.
#
# Side effects:
# When the mouse pointer is in a button, the button is
# highlighted with a broad outline and the cursor
# symbol changes to an arrow. When the active button
# is pressed, it is highlighted in green.
#
# ----------------------------------------------------------------------
proc canvasbutton::enter {w} {
variable enteredButton
variable pressedButton
variable cursor
set enteredButton [findBtag $w]
set frame [linsert $enteredButton end frame]
set cursor($w) [$w cget -cursor]
$w configure -cursor arrow
#$w itemconfigure $frame -width 3
$w itemconfigure $frame -fill grey93
if {![string compare $enteredButton $pressedButton]} {
$w itemconfigure $frame -fill grey60
}
}
# ----------------------------------------------------------------------
#
# canvasbutton::leave --
#
# Process the <Leave> event on a canvas-button.
#
# Parameters:
# w Path name of the canvas
#
# Results:
# None.
#
# Side effects:
# Reverts the cursor symbol, the border width
# if needed, the highlight color of the button.
#
# ----------------------------------------------------------------------
proc canvasbutton::leave {w} {
variable enteredButton
variable pressedButton
variable cursor
if {[string compare $enteredButton {}]} {
set btag [findBtag $w]
set frame [linsert $btag end frame]
#$w itemconfigure $frame -width 1
$w itemconfigure $frame -fill lightgray
$w configure -cursor $cursor($w)
unset cursor($w)
if {![string compare $btag $pressedButton]} {
$w itemconfigure $frame -fill white
}
set enteredButton {}
}
return
}
# ----------------------------------------------------------------------
#
# canvasbutton::press --
#
# Process the <ButtonPress-1> event on a canvas-button.
#
# Parameters:
# w Path name of the canvas
#
# Results:
# None.
#
# Side effects:
# Highlights the selected button in green.
#
# ----------------------------------------------------------------------
proc canvasbutton::press {w} {
variable pressedButton
set pressedButton [findBtag $w]
$w itemconfigure [linsert $pressedButton end frame] \
-fill grey60
return
}
# ----------------------------------------------------------------------
#
# canvasbutton::release --
#
# Process the <ButtonRelease-1> event on a canvas-button.
#
# Parameters:
# w Path name of the canvas
#
# Results:
# None.
#
# Side effects:
# Reverts the highlight color on the button. If the
# mouse has not left the button, invokes the button's
# command.
#
# ----------------------------------------------------------------------
proc canvasbutton::release {w} {
variable enteredButton
variable pressedButton
variable command
set pressedButtonWas $pressedButton
set pressedButton {}
$w itemconfigure [linsert $pressedButtonWas end frame] \
-fill grey93
if {![string compare $enteredButton $pressedButtonWas]} {
uplevel #0 $command($pressedButtonWas)
}
return
}
# ----------------------------------------------------------------------
#
# canvasbutton::btag --
#
# Locate the unique tag of a canvas-button
#
# Parameters:
# w Path name of the canvas
#
# Results:
# Button tag, or the null string if the current
# item is not a canvas-button
#
# Side effects:
# Searches the tag list of the current canvas item
# for a tag that begins with the string, `canvasb#',
# and returns the first two elements of the tag
# interpreted as a Tcl list.
#
# ----------------------------------------------------------------------
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 10 60 90 140 "First\nButton" {
.c itemconfigure label -text One
}
canvasbutton .c 110 60 190 140 "Second\nButton" {
.c itemconfigure label -text Two
}
canvasbutton .c 210 60 290 140 "Third\nButton" {
.c itemconfigure label -text Three
}
canvasbutton .c 240 160 290 190 "Quit" exit
}
|