Chapter 37. The Canvas Widget

The canvas widget is a general-purpose widget that you can program to display a variety of objects including arcs, images, lines, ovals, polygons, rectangles, text, and embedded windows.

Canvas widgets display objects such as lines and images, and each object can have bindings that respond to user input, or be animated under program control. The objects can be labeled with tags, and the tags can be configured with display attributes and event bindings. This chapter describes all the predefined canvas object types. Chapter 50 outlines the C programming interface for creating new canvas objects.

Canvas Coordinates

The coordinate space of the canvas has 0, 0 at the top left corner. Larger X coordinates are to the right, and larger Y coordinates are downward. The position and possibly the size of a canvas object is determined by a set of coordinates. Different objects are characterized by different numbers of coordinates. For example, text objects have two coordinates, x1 y1, that specify their anchor point. A line can have many pairs of coordinates that specify the end points of its segments. The coordinates are set when the object is created, and they can be updated later with the coords operation. By default, coordinates are in pixels. Append a coordinate with one of the following letters to change the units:

c   centimeters
i   inches
m   millimeters
p   printer points (1/72 inches)

The tk scale command, which is described on page 669, changes the mapping from pixels to other screen measures. Use it before creating the canvas.

The width and height attributes of the canvas determine the size of the viewable area. The scrollRegion attribute of the canvas determines the boundaries of the canvas. Its value is four numbers that specify the upper-left and lower-right coordinates of the canvas. If you do not specify a scroll region, it defaults to the size of the viewable area. Example 37-1 creates a canvas that has a 1000 by 400 scrolling region, and a 300 by 200 viewing area. The canvas is connected to two scrollbars to provide horizontal and vertical scrolling:

Example 37-1. A large scrolling canvas

proc Scrolled_Canvas { c args } {
   frame $c
   eval {canvas $c.canvas 
      -xscrollcommand [list $c.xscroll set] 
      -yscrollcommand [list $c.yscroll set] 
      -highlightthickness 0 
      -borderwidth 0} $args
   scrollbar $c.xscroll -orient horizontal 
      -command [list $c.canvas xview]
   scrollbar $c.yscroll -orient vertical 
      -command [list $c.canvas yview]
   grid $c.canvas $c.yscroll -sticky news
   grid $c.xscroll -sticky ew
   grid rowconfigure $c 0 -weight 1
   grid columnconfigure $c 0 -weight 1
   return $c.canvas
}
Scrolled_Canvas .c -width 300 -height 200 
   -scrollregion {0 0 1000 400}
=> .c.canvas
pack .c -fill both -expand true

Note

A large scrolling canvascanvaslarge scroll area

Borders are drawn in the canvas.

The highlight thickness and border width are set to 0 in Example 37-1. Otherwise, these features occupy some of the canvas viewable area. If you want a raised border for your canvas, either use another frame, or remember to offset your positions to avoid having objects clipped by the borders.

Hello, World!

Example 37-2 creates an object that you can drag around with the mouse. It introduces the use of tags to classify objects. In this case the movable tag gets bindings that let you drag the item, so any item with the movable tag shares this behavior. The example uses Scrolled_Canvas from Example 37-1. When you use a scrolled canvas, you must map from the view coordinates reported by bindings to the canvas coordinates used to locate objects:

Example 37-2. The canvas "Hello, World!" example

proc CanvasHello {} {
   set can [Scrolled_Canvas .c -width 400 -height 100 
      -scrollregion {0 0 800 400}]
   pack .c -fill both -expand true
   # Create a text object on the canvas
   $can create text 50 50 -text "Hello, World!" -tag movable
   # Bind actions to objects with the movable tag
   $can bind movable <Button-1> {CanvasMark %x %y %W}
   $can bind movable <B1-Motion> {CanvasDrag %x %y %W}
}
proc CanvasMark { x y can} {
   global canvas
   # Map from view coordinates to canvas coordinates
   set x [$can canvasx $x]
   set y [$can canvasy $y]
   # Remember the object and its location
   set canvas($can,obj) [$can find closest $x $y]
   set canvas($can,x) $x
   set canvas($can,y) $y
}
proc CanvasDrag { x y can} {
   global canvas
   # Map from view coordinates to canvas coordinates
   set x [$can canvasx $x]
   set y [$can canvasy $y]
   # Move the current object
   set dx [expr $x - $canvas($can,x)]
   set dy [expr $y - $canvas($can,y)]
   $can move $canvas($can,obj) $dx $dy
   set canvas($can,x) $x
   set canvas($can,y) $y
}

Example 37-2 creates a text object and gives it a tag named movable:

.c create text 50 50 -text "Hello, World!" -tag movable

The first argument after create specifies the type, and the remaining arguments depend on the type of object being created. Each canvas object requires some coordinates, optionally followed by attribute value pairs. The coordinates can be provided as separate arguments or, beginning in Tk 8.3, as a single-argument list. The complete set of attributes for canvas objects are presented later in this chapter. A text object needs two coordinates for its location.

Canvas Tags

The create operation returns an ID for the object being created, which would have been 1 in this case. However, the code manipulates the canvas objects by specifying a tag instead of an object ID. A tag is a more general handle on canvas objects. Many objects can have the same tag, and an object can have more than one tag. You can define bindings on tags, and you can define attributes for tags that will be picked up by objects with those tags.

A tag name can be almost any string, but you should avoid spaces that can cause parsing problems and pure numbers that get confused with object IDs. There are two predefined tags: current and all. The current tag applies to whatever object is under the mouse. The all tag applies to all the objects on the canvas.

Many of the canvas operations take an argument that identifies objects. The value can be a tag name, or it can be the numerical object identifier returned by the create operation. Also, beginning in Tk 8.3, you can specify (as a single argument) a logical combination of tags using the operators && (and), || (or), ^ (exclusive or), ! (not), and parenthesized subexpressions. For example, to change the fill color to red on all objects with a tag of highlight or warning, you could execute the following:

$can itemconfigure {highlight || warning} -fill red

To move all the objects with the tag plot1 or plot2, but that don't also include the tag fixed:

$can move {(plot1 || plot2) && !fixed} 50 0

Example 37-2 on page 559 defines behavior for objects with the movable tag. Pressing button 1 starts a drag, and dragging with the mouse button down moves the object. The pathname of the canvas (%W) is passed to CanvasMark and CanvasDrag so these procedures can be used on different canvases. The %x and %y keywords get substituted with the X and Y coordinate of the event:

$can bind movable <Button-1> {CanvasMark %x %y %W}
$can bind movable <B1-Motion> {CanvasDrag %x %y %W}

The CanvasMark and CanvasDrag procedures let you drag the object around the canvas. Because CanvasMark is applied to any object with the movable tag, it must first find the object that was clicked on. First, the view coordinates are mapped into the canvas coordinates with the canvasx and canvasy operations:

set x [$can canvasx x]
set y [$can canvasy y]

Once you do this, you can use the find operation:

set canvas($can,obj) [$can find closest $x $y]

The actual moving is done in CanvasDrag with the move operation:

$can move $canvas($can,obj) $dx $dy

Try creating a few other object types and dragging them around, too:

$can create rect 10 10 30 30 -fill red -tag movable
$can create line 1 1 40 40 90 60 -width 2 -tag movable
$can create poly 1 1 40 40 90 60 -fill blue -tag movable

The CanvasMark and CanvasDrag procedures can be used with any canvas. They use the global array canvas to keep their state, and they parameterize the indices with the canvas pathname to avoid conflict if there is more that one canvas in the application. If you get into this coding habit early, then you will find it easy to write reusable code.

Note

Canvas Tags

Canvas tags are not persistent.

Canvas tags do not work exactly like tags in the text widget. In the text widget, a tag is completely independent of the text. You can configure a text tag before it is applied to text, and the tag configuration is remembered even if you remove it from the text. A canvas tag, in contrast, must be applied to an object before you can configure it. If you configure a canvas tag that is not applied to any objects, those settings are forgotten. If you remove all the objects that share a tag, any settings associated with those tags are forgotten.

The Min Max Scale Example

This section presents Example 37-3, which constructs a scale-like object with two sliders. The sliders represent the minimum and maximum values for some parameter. Clearly, the minimum cannot be greater than the maximum, and vice versa. The example creates three rectangles on the canvas. One rectangle forms the long axis of the slider that represents the range of possible values. The other two rectangles are markers that represent the values. Two text objects float below the markers to give the current values of the minimum and maximum.

The example introduces four canvas operations: bbox, coords, scale, and move. The bbox operation returns the bounding box of an object or of all objects with a given tag. The coords operation sets or queries the coordinates of an object. The scale operation stretches an object, and the move operation translates the position of an object.

Note

Use tags instead of object IDs.

The Min Max Scale Example

Example 37-3. A min max scale canvas example

A min max scale canvas examplecanvasmin max scale
proc Scale2 {w min max {width {}} } {
   global scale2
   if {$width == {}} {
      # Set the long dimension, in pixels
      set width [expr $max - $min]
   }
   # Save parameters
   set scale2($w,scale) [expr ($max-$min)/$width.0]
   set scale2($w,min) $min;# Current minimum
   set scale2($w,max) $max
   set scale2($w,Min) $min;# Lower bound to the scale
   set scale2($w,Max) $max
   set scale2($w,L) 10
   set scale2($w,R) [expr $width+10]

   # Build from 0 to 100, then scale and move it later.
   # Distance between left edges of boxes is 100.
   # The box is 10 wide, therefore the slider is 110 long.
   # The left box sticks up, and the right one hangs down.

   canvas $w
   $w create rect 0 0 110 10 -fill grey -tag slider
   $w create rect 0 -4 10 10 -fill black -tag {left lbox}
   $w create rect 100 0 110 14 -fill red -tag {right rbox}
   $w create text 5 16 -anchor n -text $min -tag {left lnum}
   $w create text 105 16 -anchor n -text $max 
      -tag {right rnum} -fill red

   # Stretch/shrink the slider to the right length
   set scale [expr ($width+10) / 110.0]
   $w scale slider 0 0 $scale 1.0

   # move the right box and text to match new length
   set nx [lindex [$w coords slider] 2]
   $w move right [expr $nx-110] 0
   # Move everything into view
   $w move all 10 10

   # Make the canvas fit comfortably around the image
   set bbox [$w bbox all]
   set height [expr [lindex $bbox 3]+4]
   $w config -height $height -width [expr $width+30]

   # Bind drag actions
   $w bind left  <Button-1> {Scale2Mark %W %x lbox}
   $w bind right <Button-1> {Scale2Mark %W %x rbox}
   $w bind left  <B1-Motion> {Scale2Drag %W %x lbox}
   $w bind right <B1-Motion> {Scale2Drag %W %x rbox}
}

The slider is constructed with absolute coordinates, and then it is scaled to the desired width. The alternative is to compute the coordinates based on the desired width. I have found it clearer to use numbers when creating the initial layout as opposed to using expr or introducing more variables. The scale operation stretches the slider bar to the correct length. The scale operation takes a reference point, which in our case is (0, 0), and independent scale factors for the X and Y dimensions. The scale factor is computed from the width parameter, taking into account the extra length added (10) so that the distance between the left edge of the slider boxes is $width:

set scale [expr ($width+10) / 110.0]
$w scale slider 0 0 $scale 1.0

The move operation repositions the right box and right hanging text. If the marker boxes are scaled, their shape gets distorted. The coords operation returns a list of four numbers: x1 y1 x2 y2. The distance to move is just the difference between the new right coordinate and the value used when constructing the slider initially. The box and text share the same tag, right, so they are both moved with a single move operation:

set nx [lindex [$w coords slider] 2]
$w move right [expr $nx-110] 0

After the slider is constructed, it is shifted away from (0, 0), which is the upper-left corner of the canvas. The bbox operation returns four coordinates: x1 y1 x2 y2, that define the bounding box of the items with the given tag. In the example, y1 is zero, so y2 gives us the height of the image. The information returned by bbox can be off by a few pixels, and the example needs a few more pixels of height to avoid clipping the text. The width is computed based on the extra length added for the marker box, the 10 pixels the whole image was shifted, and 10 more for the same amount of space on the right side:

set bbox [$w bbox all]
set height [expr [lindex $bbox 3]+4]
$w config -height $height -width [expr $width+30]

Bindings are defined for the box and hanging text. The general tags left and right are used for the bindings. This means that you can drag either the box or the text to move the slider. The pathname of the canvas is passed into these procedures so that you could have more than one double slider in your interface:

$w bind left  <Button-1> {Scale2Mark %W %x lbox}
$w bind right <Button-1> {Scale2Mark %W %x rbox}
$w bind left  <B1-Motion> {Scale2Drag %W %x lbox}
$w bind right <B1-Motion> {Scale2Drag %W %x rbox}

Example 37-4. Moving the markers for the min max scale

proc Scale2Mark { w x what } {
   global scale2
   # Remember the anchor point for the drag
   set scale2($w,$what) $x
}
proc Scale2Drag { w x what } {
   global scale2

   # Compute delta and update anchor point
   set x1 $scale2($w,$what)
   set scale2($w,$what) $x
   set dx [expr $x - $x1]

   # Find out where the boxes are currently
   set rx [lindex [$w coords rbox] 0]
   set lx [lindex [$w coords lbox] 0]

   if {$what == "lbox"} {
      # Constrain the movement to be between the
      # left edge and the right marker.
      if {$lx + $dx > $rx} {
         set dx [expr $rx - $lx]
         set scale2($w,$what) $rx
      } elseif {$lx + $dx < $scale2($w,L)} {
         set dx [expr $scale2($w,L) - $lx]
         set scale2($w,$what) $scale2($w,L)
      }
      $w move left $dx 0

      # Update the minimum value and the hanging text
      set lx [lindex [$w coords lbox] 0]
      set scale2($w,min) [expr int($scale2($w,Min) + 
         ($lx-$scale2($w,L)) * $scale2($w,scale))]
      $w itemconfigure lnum -text $scale2($w,min)
   } else {
      # Constrain the movement to be between the
      # right edge and the left marker
      if {$rx + $dx < $lx} {
         set dx [expr $lx - $rx]
         set scale2($w,$what) $lx
      } elseif {$rx + $dx > $scale2($w,R)} {
         set dx [expr $scale2($w,R) - $rx]
         set scale2($w,$what) $scale2($w,R)
      }
      $w move right $dx 0

      # Update the maximum value and the hanging text
      set rx [lindex [$w coords right] 0]
      set scale2($w,max) [expr int($scale2($w,Min) + 
         ($rx-$scale2($w,L)) * $scale2($w,scale))]
      $w itemconfigure rnum -text $scale2($w,max)
   }
}
proc Scale2Value {w} {
   global scale2
   # Return the current values of the double slider
   return [list $scale2($w,min) $scale2($w,max)]
}

The Scale2Mark procedure initializes an anchor position, scale2($w,$what), and Scale2Drag uses this to detect how far the mouse has moved. The change in position, dx, is constrained so that the markers cannot move outside their bounds. The anchor is updated if a constraint was used, and this means that the marker will not move until the mouse is moved back over the marker. (Try commenting out the assignments to scale2($w,$what) inside the if statement.) After the marker and hanging text are moved, the value of the associated parameter is computed based on the parameters of the scale. The Scale2Value procedure queries the current values of the double slider.

Canvas Objects

The next several sections describe the built-in object types for the canvas: arc, bitmap, image, line, oval, polygon, rectangle, text, and window. Each object has its own set of attributes, and some attributes are found on most or all object types. Table 37-1 lists the common item attributes found on all or most objects. All -active and -disabled attributes were added in Tk 8.3, as were the -state attribute, the -offset attribute, and those attributes related to dashes.

Table 37-1. Common canvas item attributes

-dash pattern
-activedash pattern
-disableddash pattern

The dash pattern of the line or outline when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3)

-dashoffset offset

The starting offset distance into the pattern provided by the -dash option. (Tk 8.3)

-fill color
-activefill color
-disabledfill color

The color of the interior of the object when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -fill)

-stipple bitmap
-activestipple bitmap
-disabledstipple bitmap

The stipple pattern for the fill when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -stipple)

-offset offset

The stipple offset in the form x,y or side. side can be n, ne, e, se, s, sw, w, nw, or center. x,y is a distance relative to the canvas origin; putting # in front of the coordinate pair indicates using the toplevel origin instead. (Tk 8.3)

-outline color
-activeoutline color
-disabledoutline color

The color of the outline when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -outline)

-outlinestipple bitmap
-activeoutlinestipple bitmap
-disabledoutlinestipple bitmap

The stipple pattern for the outline when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -outlinestipple)

-width num
-activewidth num
-disabledwidth num

Width, in canvas coordinates, of the line or outline when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -width)

-state state

normal, disabled, or hidden. This overrides the canvas widget's state attribute. (Tk 8.3)

-tags tagList

List of tags for the object.

Every object has a -tags attribute used to label the object with a list of symbolic names. Most objects, even text objects, specify their color with the -fill attribute; only the bitmap object uses -foreground and -background. If the object has a border, the color of the border is specified with -outline, and the thickness of the outline is specified with -width. Starting in Tk 8.3, lines and objects with borders have a variety of -dash attributes for drawing dashed lines and borders.

Canvas Widget and Canvas Object State Options

Tk 8.3 added the -state attribute to the canvas widget and all canvas objects. The canvas state attribute can be set to normal (the default) or disabled, which provides a default state for all objects on the canvas. If an individual canvas object's -state attribute is the empty string (the default), then it inherits the canvas state. However, you can override the “global” canvas state for an individual object by setting its -state attribute to normal, disabled, or hidden.

An object in the normal state is visible and any bindings defined for it are fully functional. Additionally, if the mouse is over a normal object, it is activated and any -active* attributes defined for the object take effect. As you would expect, an object in the hidden state is not visible, and its bindings are inactive. An object in the disabled state is visible, but its bindings are inactive and it does not activate when the mouse is over it; additionally, any -disabled* attributes defined for the object take effect.

Dashed Lines

Tk 8.3 introduced the ability to draw lines and object outlines using dashed lines. The primary object attribute for controlling the dash pattern is -dash, although -activedash and -disableddash attributes are available for controlling the dash pattern in different object states.

Each of these attributes accepts a dash pattern as a value. One dash pattern format is a list of integers. Each element represents the number of pixels of a line segment. Only the odd segments are drawn using the -outline color. The other segments are drawn transparent. For example the following command draws a line with 6-pixel dashes separated by 2-pixel spaces:

$c create line -dash {6 2}

The other dash pattern format is a string containing any combination of the characters shown in Table 37-2.

Table 37-2. Canvas dash pattern characters

.

Dash 1/2 of the length of the following space

,

Dash equal to the length of the following space

-

Dash 1 1/2 times the length of the following space

_

Dash double the length of the following space

space

Doubles the length of the space

For example, the dash pattern {_. ,} is roughly equivalent to {8 4 2 8 4 4}

The main difference of the string-based syntax versus the list-based syntax is that it the string-based syntax is shape-conserving. This means that all values in the dash list are multiplied by the line width before display. This assures that “.” is always displayed as a dot and “-” as a dash regardless of the line width.

Finally, the -dashoffset attribute specifies the starting offset (in pixels) into the pattern provided by -dash.

Note

Not all dash patterns are supported on all platforms.

On systems that support only a limited set of dash patterns, the dash pattern is displayed as the closest dash pattern that is available. For example, on Windows the dash patterns {.} and {,} and {. } and {, } are displayed identically.

Arc Items

An arc is a section of an oval. The dimensions of the oval are determined by four coordinates that are its bounding box. The arc is then determined by two angles, the start angle and the extent. The region of the oval can be filled or unfilled, and there are three different ways to define the fill region. The pieslice style connects the arc with the center point of the oval. The chord style connects the two end points of the arc. The arc style just draws the arc itself and there is no fill. Example 37-5 shows three arcs with the same bounding box but different styles and angles:

Example 37-5. Canvas arc items

Canvas arc items
# $c is a canvas
$c create arc 10 10 100 100 -start 45 -extent -90 
   -style pieslice -fill orange -outline black
$c create arc 10 10 100 100 -start 135 -extent 90 
   -style chord -fill blue -outline white -width 4
$c create arc 10 10 100 100 -start 255 -extent 45 
   -style arc -outline black -width 3

An arc object support all of the object attributes listed in Table 37-1. Table 37-3 lists the additional attributes supported by arc objects.

Table 37-3. Arc attributes

-extent degrees

The length of the arc in the counter-clockwise direction.

-start degrees

The starting angle of the arc.

-style style

pieslice, chord, arc.

Bitmap Items

A bitmap is a simple graphic with a foreground and background color. One bit per pixel is used to choose between the foreground and the background. If you do not specify a background color, the background bits are clear and the canvas background shows through. A canvas bitmap item is positioned with two coordinates and an anchor position. Its size is determined by the bitmap data. The bitmap itself is specified with a symbolic name or by the name of a file that contains its definition. If the name begins with an @, it indicates a file name. The bitmaps built into Tk are shown in the example below. Chapter 50 outlines the C interface for registering bitmaps under a name.

Example 37-6. Canvas bitmap items

Canvas bitmap items
set o [$c create bitmap 10 10 -bitmap @candle.xbm -anchor nw
   -background white -foreground blue]
set x [lindex [$c bbox $o] 2] ;# Right edge of bitmap
foreach builtin {error gray12 gray50 hourglass 
             info questhead question warning} {
   incr x 20
   set o [$c create bitmap $x 30 -bitmap $builtin -anchor c]
   set x [lindex [$c bbox $o] 2]
}

A bitmap object supports only the -state and -tags attributes listed in Table 37-1. Table 37-4 lists the additional attributes supported by bitmap objects.

Table 37-4. Bitmap attributes

-anchor position

Anchorc (default), n, ne, e, se, s, sw, w, or nw.

-background color
-activebackground color
-disabledbackground color

The background color (for zero bits) when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -background)

-bitmap name
-activebitmap name
-disabledbitmap name

The bitmap to display when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -bitmap)

-foreground color
-activeforeground color
-disabledforeground color

The foreground color (for one bits) when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -foreground)

Image Items

The canvas image objects use the general image mechanism of Tk. You must first define an image using the image command, which is described in Chapter 41 in the section Bitmaps and Images. Once you have defined an image, all you need to specify for the canvas is its position, anchor point, and any tags. The size and color information is set when the image is defined. If an image is redefined, anything displaying that image automatically gets updated. Example 37-7 creates one image and puts six instances of it on a canvas:

Example 37-7. Canvas image items

Canvas image items
image create bitmap hourglass2 
   -file hourglass.bitmap -maskfile hourglass.mask 
   -background white -foreground blue
for {set x 20} {$x < 300} {incr x 20} {
   $c create image $x 10 -image hourglass2 -anchor nw
   incr x [image width hourglass2]
}

An image object supports only the -state and -tags attributes listed in Table 37-1. Table 37-5 lists the additional attributes supported by image objects.

Table 37-5. Image attributes

-anchor position

Anchorc (default), n, ne, e, se, s, sw, w, or nw.

-image name
-activeimage name
-disabledimage name

The name of an image to use when in the normal, active (the mouse over the object), and disabled states. (Tk 8.3, except -image)

Line Items

A line has two or more sets of coordinates, where each set of coordinates defines an end point of a line segment. The segments can be joined in several different styles, and the whole line can be drawn with a spline fit as opposed to straight-line segments. The next example draws a line in two steps. In the first pass, single-segment lines are drawn. When the stroke completes, these are replaced with a single line segment that is drawn with a spline curve.

Example 37-8. A canvas stroke drawing example

A canvas stroke drawing examplecanvasstroke drawing example
proc StrokeInit {} {
   canvas .c ; pack .c
   bind .c <Button-1> {StrokeBegin %W %x %y}
   bind .c <B1-Motion> {Stroke %W %x %y}
   bind .c <ButtonRelease-1> {StrokeEnd %W %x %y}
}
proc StrokeBegin { w x y } {
   global stroke
   catch {unset stroke}
   set stroke(N) 0
   set stroke(0) [list $x $y]
}
proc Stroke { w x y } {
   global stroke
   set coords $stroke($stroke(N))
   lappend coords $x $y
   incr stroke(N)
   set stroke($stroke(N)) [list $x $y]
   # eval gets the coordinates into individual arguments
   eval {$w create line} $coords {-tag segments}
}
proc StrokeEnd { w x y } {
   global stroke
   set coords {}
   for {set i 0} {$i <= $stroke(N)} {incr i} {
      append coords $stroke($i) " "
   }
   $w delete segments
   eval {$w create line} $coords 
      {-tag line -joinstyle round -smooth true -arrow last}
}
A canvas stroke drawing examplecanvasstroke drawing example

The arrow attribute adds an arrow head to the end of the stroke. If you try this example you will notice that the arrow is not always aimed as you expect. This is because there are often many points generated close together as you release the mouse button. In fact, the X and Y coordinates seen by StrokeEnd are always the same as those seen by the last Stroke call. If you add this duplicate point to the end of the list of points, no arrowhead is drawn at all. In practice you might want to make Stroke filter out points that are too close together.

A line object supports all of the attributes listed in Table 37-1 except for -offset, the -outline family of attributes, and the -outlinestipple family of attributes. Remember that the -fill attribute controls the color in which the line is drawn (not the -outline attribute, as is common for other canvas items). Table 37-6 lists the additional attributes supported by line objects. The capstyle affects the way the ends of the line are drawn. The joinstyle affects the way line segments are joined together. The capstyle and joinstyle attributes are from the X window system and may not be implemented on the Macintosh and Windows platforms.

Table 37-6. Line attributes

-arrow where

Arrow locationnone, first, last, or both.

-arrowshape {a b c}

Three parameters that describe the shape of the arrow. c is the width and b is the overall length. a is the length of the part that touches the line (e.g., 8 10 3).

-capstyle what

Line endsbutt, projecting, or round.

-joinstyle what

Line jointsbevel, miter, or round.

-smooth boolean

If true, a spline curve is drawn.

-splinesteps num

Number of line segments that approximate the spline.

Oval Items

An oval is defined by two sets of coordinates that define its bounding box. If the box is square, a circle is drawn. You can set the color of the interior of the oval as well as the outline of the oval. A sampler of ovals is shown in Example 37-9.

Example 37-9. Canvas oval items

Canvas oval items
$c create oval 10 10 80 80 -fill red -width 4
$c create oval 100 10 150 80 -fill blue -width 0
$c create oval 170 10 250 40 -fill black -stipple gray12

An oval object support all of the object attributes listed in Table 37-1. There are no additional attributes supported by oval objects.

Polygon Items

A polygon is a closed shape specified by sets of points, one for each vertex of the polygon. The vertices can be connected with smooth or straight lines. Example 37-10 creates a stop sign. The picture is centered at (0, 0) and then moved fully onto the canvas:

Example 37-10. Canvas polygon items

Canvas polygon items
$c create poly 20 -40 40 -20 40 20 20 40 -20 40 
   -40 20 -40 -20 -20 -40 -fill red 
   -outline white -width 5
$c create text 0 0 -text STOP -fill white 
   -font {helvetica 18 bold}
$c move all 50 50

A polygon object support all of the object attributes listed in Table 37-1. Table 37-7 lists the additional attributes supported by polygon objects

Table 37-7. Polygon attributes

-joinstyle what

Line jointsbevel, miter, or round.

-smooth boolean

If true, a spline curve is drawn around the points.

-splinesteps num

Number of line segments that approximate the spline.

Rectangle Items

A rectangle is specified with two coordinates that are its opposite corners. A rectangle can have a fill color and an outline color. If you do not specify a fill, then the background of the canvas (or other objects) shows through. If you stipple the fill, the background also shows through the clear bits of the stipple pattern. You must use a second rectangle if you want the stippled fill to completely hide what is behind it. Example 37-11 drags out a box as the user drags the mouse. All it requires is remembering the last rectangle drawn so that it can be deleted when the next box is drawn:

Example 37-11. Dragging out a box

proc BoxInit {} {
   canvas .c -bg white ; pack .c
   bind .c <Button-1> {BoxBegin %W %x %y}
   bind .c <B1-Motion> {BoxDrag %W %x %y}
}
proc BoxBegin { w x y } {
   global box
   set box($w,anchor) [list $x $y]
   catch {unset box($w,last)}
}
proc BoxDrag { w x y } {
   global box
   catch {$w delete $box($w,last)}
   set box($w,last) [eval {$w create rect} $box($w,anchor) 
      {$x $y -tag box}]
}

The example uses box($w,anchor) to record the start of the box. This is a list with the X and Y coordinates. The eval command is used so that this list can be spliced into the create rect command. Note that as of Tk 8.3 this would not be necessary as the create rect command can now accept a list of coordinates as a single argument.

A rectangle object support all of the object attributes listed in Table 37-1. There are no additional attributes supported by rectangle objects.

Text Items

The canvas text item provides yet another way to display and edit text. It supports selection, editing, and it can extend onto multiple lines. The position of a text item is specified by one set of coordinates and an anchor position. The size of the text is determined by the number of lines and the length of each line. A new line is started if there is a newline in the text string. If a width is specified, in screen units, then any line that is longer than this is wrapped onto multiple lines. The wrap occurs before a space character.

The editing and selection operations for text items use indices to specify positions within a given text item. These are very similar to those used in the entry widget. Table 37-8 summarizes the indices for canvas text items.

Table 37-8. Indices for canvas text items

0

Index of the first character.

end

Index just past the last character.

number

Index a character, where number counts from zero.

insert

Index of the character right after the insertion cursor.

sel.first

Index of the first character in the selection.

sel.last

Index of the last character in the selection.

@x,y

Index of the character under the specified X and Y coordinate.

There are several canvas operations that manipulate text items. These are similar to some of the operations of the entry widget. The dchars and select to operations treat the second index differently than the corresponding operations in the entry and text widget. The character at the second index is included in the operation (e.g., deleted), while in the entry and text widget it is not.

The canvas text operations are parameterized by the tag or ID of the canvas object being manipulated. If the tag refers to more than one object, then the operations apply to the first object in the display list that supports an insert cursor. The display list is described on page 581. Table 37-9 summarizes the operations on text items. In the table $t is a text item or tag and $c is a canvas.

Table 37-9. Canvas operations that apply to text items

$c dchars $t first ?last?

Deletes the characters from first through last, or just the character at first.

$c focus ?$t?

Sets input focus to the specified item, or returns the ID of the item with the focus if it is not given.

$c icursor $t index

Sets the insert cursor to just before index.

$c index $t index

Returns the numerical value of index.

$c insert $t index string

Inserts the string just before index.

$c select adjust $t index

Moves the boundary of an existing selection.

$c select clear

Clears the selection.

$c select from $t index

Starts a selection.

$c select item

Returns the ID of the selected item, if any.

$c select to $t index

Extends the selection to the specified index.

There are no default bindings for canvas text items. Example 37-12 sets up some basic bindings for canvas text items. The <Button-1> and <Button-2> bindings are on the canvas as a whole. The rest of the bindings are on items with the text tag. You must add the text tag to text items that should share the editable text behavior. Small procedures are introduced for each binding to hide the details and any local variables needed in the operations.

Note

Canvas operations that apply to text items

Canvas find overlapping vs. find closest.

The CanvasFocus procedure uses the canvas find overlapping operation to see if a text object has been clicked. This must be used because find closest finds an object no matter how far away it is. It also uses the type operation to make sure only text objects are given the focus. If you want other object types to respond to key events, you should change that.

The CanvasPaste procedure does one of two things. It pastes the selection into the canvas item that has the focus. If no item has the focus, then a new text item is created with the selection as its value:

Example 37-12. Simple edit bindings for canvas text items

proc Canvas_EditBind { c } {
   bind $c <Button-1> 
      {CanvasFocus %W [%W canvasx %x] [%W canvasy %y]}
   bind $c <Button-2> 
      {CanvasPaste %W [%W canvasx %x] [%W canvasy %y]}
   bind $c <<Cut>> {CanvasTextCopy %W; CanvasDelete %W}
   bind $c <<Copy>> {CanvasTextCopy %W}
   bind $c <<Paste>> {CanvasPaste %W}
   $c bind text <Button-1> 
      {CanvasTextHit %W [%W canvasx %x] [%W canvasy %y]}
   $c bind text <B1-Motion> 
      {CanvasTextDrag %W [%W canvasx %x] [%W canvasy %y]}
   $c bind text <Delete> {CanvasDelete %W}
   $c bind text <Control-d> {CanvasDelChar %W}
   $c bind text <Control-h> {CanvasBackSpace %W}
   $c bind text <BackSpace> {CanvasBackSpace %W}
   $c bind text <Control-Delete> {CanvasErase %W}
   $c bind text <Return> {CanvasNewline %W}
   $c bind text <Any-Key> {CanvasInsert %W %A}
   $c bind text <Key-Right> {CanvasMoveRight %W}
   $c bind text <Control-f> {CanvasMoveRight %W}
   $c bind text <Key-Left> {CanvasMoveLeft %W}
   $c bind text <Control-b> {CanvasMoveLeft %W}
}
proc CanvasFocus {c x y} {
   focus $c
   set id [$c find overlapping [expr $x-2] [expr $y-2] 
         [expr $x+2] [expr $y+2]]
   if {($id == {}) || ([$c type $id] != "text")} {
      set t [$c create text $x $y -text "" 
         -tags text -anchor nw]
      $c focus $t
      $c select clear
      $c icursor $t 0
   }
}
proc CanvasTextHit {c x y {select 1}} {
   $c focus current
   $c icursor current @$x,$y
   $c select clear
   $c select from current @$x,$y
}
proc CanvasTextDrag {c x y} {
   $c select to current @$x,$y
}
proc CanvasDelete {c} {
   if {[$c select item] != {}} {
      $c dchars [$c select item] sel.first sel.last
   } elseif {[$c focus] != {}} {
      $c dchars [$c focus] insert
   }
}
proc CanvasTextCopy {c} {
   if {[$c select item] != {}} {
      clipboard clear
      set t [$c select item]
      set text [$c itemcget $t -text]
      set start [$c index $t sel.first]
      set end [$c index $t sel.last]
      clipboard append [string range $text $start $end]
   } elseif {[$c focus] != {}} {
      clipboard clear
      set t [$c focus]
      set text [$c itemcget $t -text]
      clipboard append $text
   }
}
proc CanvasDelChar {c} {
   if {[$c focus] != {}} {
      $c dchars [$c focus] insert
   }
}
proc CanvasBackSpace {c} {
   if {[$c select item] != {}} {
      $c dchars [$c select item] sel.first sel.last
   } elseif {[$c focus] != {}} {
      set _t [$c focus]
      $c icursor $_t [expr [$c index $_t insert]-1]
      $c dchars $_t insert
   }
}
proc CanvasErase {c} {
   $c delete [$c focus]
}
proc CanvasNewline {c} {
   $c insert [$c focus] insert 

}
proc CanvasInsert {c char} {
   $c insert [$c focus] insert $char
}
proc CanvasPaste {c {x {}} {y {}}} {
   if {[catch {selection get} _s] &&
       [catch {selection get -selection CLIPBOARD} _s]} {
      return      ;# No selection
   }
   set id [$c focus]
   if {[string length $id] == 0 } {
      set id [$c find withtag current]
   }
   if {[string length $id] == 0 } {
      # No object under the mouse
      if {[string length $x] == 0} {
         # Keyboard paste
         set x [expr [winfo pointerx $c] - [winfo rootx $c]]
         set y [expr [winfo pointery $c] - [winfo rooty $c]]
      }
      CanvasFocus $c $x $y
   } else {
      $c focus $id
   }
   $c insert [$c focus] insert $_s
}

proc CanvasMoveRight {c} {
   $c icursor [$c focus] [expr [$c index current insert]+1]
}
proc CanvasMoveLeft {c} {
   $c icursor [$c focus] [expr [$c index current insert]-1]
}

Of the attributes listed in Table 37-1, text objects support only the -fill family of attributes, the -stipple family of attributes, and the -state and -tags attributes. Table 37-10 specifies the additional attributes for text items. Note that there are no foreground and background attributes. Instead, the fill color specifies the color for the text. It is possible to stipple the text as well. Additionally, the -width attribute is treated differently than for other canvas objects.

Table 37-10. Text attributes

-anchor position

Anchorc (default), n, ne, e, se, s, sw, w, or nw.

-font font

The font for the text.

-justify how

Justificationleft, right, or center.

-text string

The string to display.

-width width

The width, in screen units, before text is wrapped

Window Items

Window Items

Example 37-13. Using a canvas to scroll a set of widgets

proc Example37–13 { top title labels } {
   # Create a resizable toplevel window
   toplevel $top
   wm minsize $top 200 100
   wm title $top $title

   # Create a frame for buttons,
   # Only Dismiss does anything useful
   set f [frame $top.buttons -bd 4]
   button $f.quit -text Dismiss -command "destroy $top"
   button $f.save -text Save
   button $f.reset -text Reset
   pack $f.quit $f.save $f.reset -side right
   pack $f -side top -fill x

   # Create a scrolling canvas
   frame $top.c
   canvas $top.c.canvas -width 10 -height 10 
      -yscrollcommand [list $top.c.yscroll set]
   scrollbar $top.c.yscroll -orient vertical 
      -command [list $top.c.canvas yview]
   pack $top.c.yscroll -side right -fill y
   pack $top.c.canvas -side left -fill both -expand true
   pack $top.c -side top -fill both -expand true

   Scrolled_EntrySet $top.c.canvas $labels
}
proc Scrolled_EntrySet { canvas labels } {
   # Create one frame to hold everything
   # and position it on the canvas
   set f [frame $canvas.f -bd 0]
   $canvas create window 0 0 -anchor nw -window $f

   # Create and grid the labeled entries
   set i 0
   foreach label $labels {
      label $f.label$i -text $label
      entry $f.entry$i
      grid $f.label$i $f.entry$i
      grid $f.label$i -sticky w
      grid $f.entry$i -sticky we
      incr i
   }
   set child $f.entry0

   # Wait for the window to become visible and then
   # set up the scroll region based on
   # the requested size of the frame, and set
   # the scroll increment based on the
   # requested height of the widgets

   tkwait visibility $child
   set bbox [grid bbox $f 0 0]
   set incr [lindex $bbox 3]
   set width [winfo reqwidth $f]
   set height [winfo reqheight $f]
   $canvas config -scrollregion "0 0 $width $height"
   $canvas config -yscrollincrement $incr
   set max [llength $labels]
   if {$max > 10} {
      set max 10
   }
   set height [expr $incr * $max]
   $canvas config -width $width -height $height
}
Example37–13 .ex "An example" {
   alpha beta gamma delta epsilon zeta eta theta iota kappa
   lambda mu nu xi omicron pi rho sigma tau upsilon
   phi chi psi omega}
Using a canvas to scroll a set of widgetsscrollbarwidgets on a canvas

A window object supports only the -state and -tags attributes listed in Table 37-1. Table 37-11 lists the additional attributes supported by window objects. Note that the -width attribute is treated differently than for other canvas objects.

Table 37-11. Window attributes

-anchor position

Anchorc (default), n, ne, e, se, s, sw, w, or nw.

-height height

The height, in screen units, for the widget. If the value is an empty string (default), then the window is given whatever height it requests internally.

-width width

The width, in screen units, for the widget. If the value is an empty string (default), then the window is given whatever width it requests internally.

-window name

The name of the widget to display within the canvas.

Canvas Operations

Table 37-12 summarizes the operations on canvas widgets. In the table, $c is a canvas. $t represents a numerical object ID, a canvas tag or — in Tk 8.3 or later — a logical combination of tags using the operators && (and), || (or), ^ (exclusive or), ! (not), and parenthesized subexpressions, grouped as a single argument (for example, {(plot1 || plot2) && !fixed}). In some cases, an operation only applies to a single object. In these cases, if a tag or tag expression identifies several objects, the first object in the display list is operated on.

The canvas display list refers to the global order among canvas objects. New objects are put at the end of the display list. Objects later in the display list obscure objects earlier in the list. The term above refers to objects later in the display list.

Table 37-9 describes several of the canvas operations that only apply to text objects. They are dchars, focus, index, icursor, insert, and select. Table 37-12 does not repeat those operations.

Table 37-12. Operations on a canvas widget

$c addtag tag above $t

Adds tag to the item just above $t in the display list.

$c addtag tag all

Adds tag to all objects in the canvas.

$c addtag tag below $t

Adds tag to the item just below $t in the display list.

$c addtag tag closest x y ?halo? ?start?

Adds tag to the item closest to the x y position. If more than one object is the same distance away, or if more than one object is within halo pixels, then the last one in the display list (uppermost) is returned. If start is specified, the closest object after start in the display list is returned.

$c addtag tag enclosed x1 y1 x2 y2

Adds tag to the items completely enclosed in the specified region. x1 <= x2, y1 <= y2.

$c addtag tag overlapping x1 y1 x2 y2

Adds tag to the items that overlap the specified region. x1 <= x2, y1 <= y2.

$c addtag tag withtag $t

Adds tag to the items identified by $t.

$c bbox $t ?tag tag ...?

Returns the bounding box of the items identified by the tag(s) in the form x1 y1 x2 y2

$c bind $t ?sequence? ?command?

Sets or queries the bindings of canvas items.

$c canvasx screenx ?grid?

Maps from the X screen coordinate screenx to the X coordinate in canvas space, rounded to multiples of grid if specified.

$c canvasy screeny ?grid?

Maps from screen Y to canvas Y.

$c cget option

Returns the value of option for the canvas.

$c configure ...

Queries or updates the attributes of the canvas.

$c coords $t ?x1 y1 ...?

Queries or modifies the coordinates of the item. As of Tk 8.3, a list of coordinates can be provided as a single argument.

$c create type x y ?x2 y2 ...? ?opt value ...?

Creates a canvas object of the specified type at the specified coordinates. As of Tk 8.3, a list of coordinates can be provided as a single argument.

$c delete $t ?tag ...?

Deletes the item(s) specified by the tag(s) or ID(s).

$c dtag $t ?deltag?

Removes the specified tags from the items identified by $t. If deltag is omitted, it defaults to $t.

$c find addtagSearch ...

Returns the IDs of the tags that match the addtag search specification: above, all, below, closest, enclosed, overlapping and withtag.

$c gettags $t

Returns the tags associated with the first item identified by $t.

$c itemcget $t option

Returns the value of option for item $t.

$c itemconfigure $t ...

Queries or reconfigures item $t.

$c lower $t ?belowThis?

Moves the items identified by $t to the beginning of the display list, or just before belowThis.

$c move $t dx dy

Moves $t by the specified amount.

$c postscript ...

Generates Postscript. Table 37-13 lists options.

$c raise $t ?aboveThis?

Moves the items identified by $t to the end of the display list, or just after aboveThis.

$c scale $t x0 y0 xS yS

Scales the coordinates of the items identified by $t. The distance between x0 and a given X coordinate changes by a factor of xS. Similarly for Y.

$c scan mark x y

Sets a mark for a scrolling operation.

$c scan dragto x y

Scrolls the canvas from the previous mark.

$c type $t

Returns the type of the first item identified by $t.

$t xview

Returns two fractions between zero and one that describes the amount of the canvas off-screen to the left and the amount of the canvas displayed.

$t xview moveto fraction

Positions the canvas so that fraction of the scroll region is off screen to the left.

$t xview scroll num what

Scrolls num of what, which is units or pages.

$t yview

Returns two fractions between zero and one that describes the amount of the canvas off screen to the top and the amount of the canvas displayed.

$t yview moveto fraction

Positions the text so that fraction of the canvas scroll region is off screen toward the top.

$t yview scroll num what

Scrolls num of what, which is units or pages.

Generating Postscript

The postscript operation generates Postscript based on the contents of a canvas. One limitation in earlier versions of Tk is that images and embedded windows are not captured in the Postscript output. As of Tk 8.3, images are included in the generated Postscript. Also, as of Tk 8.3 for Unix and Tk 8.4.1 for Windows, embedded windows are included in the generated Postscript if they are currently displayed on the screen (that is, displayed within the canvas's viewport and not obscured by other windows).

Table 37-13 summarizes all the options for generating Postscript.

Table 37-13. Canvas postscript options

-channel fid

The channel identifier of a channel already opened for writing. The Postscript is written to that channel, and the channel is left open for further writing at the end of the operation. If -channel or -file are not specified, the Postscript is returned as the result of the command.

-colormap varName

The index of varName is a named color, and the contents of each element is the Postscript code to generate the RGB values for that color.

-colormode mode

mode is one of color, grey, or mono.

-file name

The file in which to write the Postscript. If -file or -channel are not specified, the Postscript is returned as the result of the command.

-fontmap varName

The index of varName is an X font name. Each element contains a list of two items: a Postscript font name and a point size.

-height size

Height of the area to print.

-pageanchor anchor

Anchorc, n, ne, e, se, s, sw, w, or nw.

-pageheight size

Height of image on the output. A floating point number followed by c (centimeters), i (inches), m (millimeters), or p (printer points).

-pagewidth size

Width of image on the output.

-pagex position

The output X coordinate of the anchor point.

-pagey position

The output Y coordinate of the anchor point.

-rotate boolean

If true, rotates so that X axis is the long direction of the page (landscape orientation).

-width size

Width of the area to print.

-x position

Canvas X coordinate of left edge of the image.

-y position

Canvas Y coordinate of top edge of the image.

You control what region of the canvas is printed with the -width, -height, -x, and -y options. You control the size and location of this in the output with the -pageanchor, -pagex, -pagey, -pagewidth, and -pageheight options. The Postscript is written to the file named by the -file option, to a channel already opened for writing whose channel identifier is provided by the -channel option, or it is returned as the value of the postscript canvas operation.

You control fonts with a mapping from X screen fonts to Postscript fonts. Define an array where the index is the name of the X font and the contents are the name and pointsize of a Postscript font.

Example 37-14 positions a number of text objects with different fonts onto a canvas. For each different X font used, it records a mapping to a Postscript font. The example has a fairly simple font mapping, and in fact the canvas would probably have guessed the same font mapping itself. If you use more exotic screen fonts, you may need to help the canvas widget with an explicit font map.

The example positions the output at the upper-left corner of the printed page by using the -pagex, -pagey, and -pageanchor options. Recall that Postscript has its origin at the lower-left corner of the page.

Example 37-14. Generating Postscript from a canvas

proc Setup {} {
   global fontMap
   canvas .c
   pack .c -fill both -expand true
   set x 10
   set y 10
   set last [.c create text $x $y -text "Font sampler" 
      -font fixed -anchor nw]

   # Create several strings in different fonts and sizes

   foreach family {times courier helvetica} {
      set weight bold
      switch -- $family {
         times { set fill blue; set psfont Times}
         courier { set fill green; set psfont Courier }
         helvetica { set fill red; set psfont Helvetica }
      }
      foreach size {10 14 24} {
         set y [expr 4+[lindex [.c bbox $last] 3]]

         # Guard against missing fonts
         if {[catch {.c create text $x $y 
                -text $family-$weight-$size 
                -anchor nw -fill $fill 
                -font -*-$family-$weight-*-*-*-$size-*} 
         it] == 0} {
            set fontMap(-*-$family-$weight-*-*-*-$size-*)
               [list $psfont $size]
            set last $it
         }
      }
   }
   set fontMap(fixed) [list Courier 12]
}
proc Postscript { c file } {
   global fontMap
   # Tweak the output color
   set colorMap(blue) {0.1 0.1 0.9 setrgbcolor}
   set colorMap(green) {0.0 0.9 0.1 setrgbcolor}
   # Position the text at the upper-left corner of
   # an 8.5 by 11 inch sheet of paper
   $c postscript -fontmap fontMap -colormap colorMap 
      -file $file 
      -pagex 0.i -pagey 11.i -pageanchor nw
}

Canvas Attributes

Table 37-14 lists the attributes for the canvas widget. The table uses the resource name, which has capitals at internal word boundaries. In Tcl commands, the attributes are specified with a dash and are all lowercase.

Table 37-14. Canvas attribute resource names

background

The normal background color.

borderWidth

The width of the border around the canvas.

closeEnough

Distance from mouse to an overlapping object.

confine

Boolean. True constrains the view to the scroll region.

cursor

Cursor to display when mouse is over the widget.

height

Height, in screen units, of canvas display.

highlightBackground

Focus highlight color when widget does not have focus.

highlightColor

Color for input focus highlight border.

highlightThickness

Width of highlight border.

insertBackground

Background for area covered by insert cursor.

insertBorderwidth

Width of cursor border. Nonzero for 3D effect.

insertOffTime

Time, in milliseconds the insert cursor blinks off.

insertOnTime

Time, in milliseconds the insert cursor blinks on.

insertWidth

Width of insert cursor. Default is 2.

relief

flat, sunken, raised, groove, solid, or ridge.

scrollRegion

Left, top, right, and bottom coordinates of the canvas.

selectBackground

Background color of selection.

selectForeground

Foreground color of selection.

selectBorderWidth

Width of selection border. Nonzero for 3D effect.

state

The default state for canvas objects: normal or disabled. (Tk 8.3)

takeFocus

Controls focus changes from keyboard traversal.

width

Width in screen units for viewable area.

xScrollCommand

Tcl command prefix for horizontal scrolling.

xScrollIncrement

Distance for one scrolling unit in the X direction.

yScrollCommand

Tcl command prefix for vertical scrolling.

yScrollIncrement

Distance for one scrolling unit in the Y direction.

The scroll region of a canvas defines the boundaries of the canvas coordinate space. It is specified as four coordinates, x1 y1 x2 y2 where (x1, y1) is the top-left corner and (x2, y2) is the lower-right corner. If the confine attribute is true, then the canvas cannot be scrolled outside this region. It is OK to position canvas objects partially or totally off the scroll region; they just may not be visible. The scroll increment attributes determine how much the canvas is scrolled when the user clicks on the arrows in the scrollbar.

The closeEnough attribute indicates how far away a position can be from an object and still be considered to overlap it. This applies to the overlapping search criteria.

Hints

Screen Coordinates vs. Canvas Coordinates

Screen Coordinates vs. Canvas Coordinatescanvascoordinates vs. screen coordinatesscreencoordinates vs. canvas coordinates
set id [$c find closest [$c canvasx %x] [$c canvasy %y]]

Large Coordinate Spaces

Coordinates for canvas items are stored internally as floating point numbers, so the values returned by the coords operation will be floating point numbers. If you have a very large canvas, you may need to adjust the precision with which you see coordinates by setting the tcl_precision variable. This is an issue if you query coordinates, perform a computation on them, and then update the coordinates. (Tcl 8.0 changed the default tcl_precision from 6 to 12.)

Scaling and Rotation

The scale operation scales the coordinates of one or more canvas items. It is not possible to scale the whole coordinate space. The main problem with this is that you can lose precision when scaling and unscaling objects because their internal coordinates are actually changed by the scale operation. For simple cases this is not a problem, but in extreme cases it can show up.

The canvas does not support rotation.

Resources

There is no resource database support built into the canvas and its items. You can, however, define resources and query them yourself. For example, you could define:

*Canvas.foreground:   blue

This would have no effect by default. However, your code could look for this resource with option get, and specify this color directly for the -fill attribute of your objects:

set fg [option get $c foreground {}]
$c create rect 0 0 10 10 -fill $fg

The main reason to take this approach is to let your users customize the appearance of canvas objects without changing your code.

Objects with Many Points

The canvas implementation seems well optimized to handle lots of canvas objects. However, if an object like a line or a polygon has many points that define it, the implementation ends up scanning through these points linearly. This can adversely affect the time it takes to process mouse events in the area of the canvas containing such an item. Apparently any object in the vicinity of a mouse click is scanned to see if the mouse has hit it so that any bindings can be fired.

Selecting Canvas Items

Example 38-5 on page 596 implements cut and paste of canvas objects. The example exchanges the logical description of canvas objects with the selection mechanism.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.22.107