9.6. Creating Items in a Canvas
The whole point of having a Canvas is to put items in it. You can
create arcs, bitmaps, images, lines, rectangles, ovals (circles),
polygons, text, and widgets. Each has an associated
createXXX method, where the
type of item you want to create replaces the
XXX. Each of the create
methods returns a unique ID, which can be used to
refer to the item later. When you see a method that takes a tag or an
ID as an argument, the ID is the one returned from the
create method.
9.6.1. The Arc Item
When you create an arc, you specify a bounding rectangle with two
sets of x and y coordinates. The arc is drawn within the confines of
the bounding box. The basic createArc statement is
as follows:
$id = $canvas->createArc(x1, y1, x2, y2);
Any additional options used with createArc are
specified after the coordinates:
$id = $canvas->createArc(x1, y1, x2, y2, option => value);
Each option for the arc item can be
used later with the itemcget and
itemconfigure Canvas methods. The options are:
- -extent => degrees
-
The length of
the arc is specified in degrees by using the
-extent option. The default
-extent (or length) is 90 degrees. The arc is
drawn from the starting point (see -start option)
counterclockwise within the rectangle defined by
(x1, y1) and
(x2, y2). The
degrees value should be between -360 and
360. If it is more or less, the value used is the specified number of
degrees modulo 360.
Here are some examples of the -extent option:
# This draws half of an oval
$canvas->createArc(0,0,100,150, -extent => 180);
# This will draw 3/4 of an oval
$canvas->createArc(0,0,100,150, -extent => 270);
- -fill => color
-
To fill the arc with the specified
color. By default, there is no fill color for an
arc.
- -outline => color
-
Normally the arc is drawn with a
black outline. To change the default, use the
-outline option. The outline color is separate
from the fill color, so to make it a completely solid object, make
the color for -outline and
-fill the same.
- -outlinestipple => bitmap
-
To
use -outlinestipple, you must also use the
-outline option. Normally the outline of the arc
is drawn solid. Use a bitmap with -outlinestipple
to make the outline nonsolid; the specified bitmap pattern will be
used to draw the outline of the arc.
- -start => degrees
-
The value
associated with the -start option determines where
Perl/Tk starts drawing the arc. The default start position is at
three o'clock (0 degrees). The specified degrees are added to
this position in a counterclockwise direction. Use -start
=> 90 to make the arc start at the twelve o'clock
position, use -start => 180
to make the arc start at the nine o'clock position, and so on.
- -stipple => bitmap
-
The -stipple
option fills the arc with a bitmap pattern, but the
-fill option must be specified as well.
- -style => "pieslice" | "chord" | "arc"
-
The -style of
the arc determines how the arc is drawn. The default,
"pieslice", draws the arc and two lines from the
center of the oval ends of the arc segment. The
"chord" value draws the arc and a line connecting
the two end points of the arc segment. The "arc"
value draws just the arc portion with no other lines. The
-fill and -stipple options are
ignored if "arc" is used.
- -tags => taglist
-
When you create an arc, you use the
-tags option to assign tag names to it. The value
associated with -tags is an anonymous array of tag
names; for example:
$canvas->createArc(0,0,10,140,-tags => ["arc", "tall"]);
You don't need to use an anonymous
array if you are only specifying one tag name:
$canvas->createArc(0,0,10,140,-tags => "arc");
- -width => amount
-
This specifies the width of the
outline. The default -width is 1.
9.6.2. The Bitmap Item
A Canvas widget can display a
bitmap instead of text, just as a Button or Label can. You can use
createBitmap to insert a bitmap into your Canvas
widget:
$id = $canvas->createBitmap(x, y);
Of course, you must use the
-bitmap option to specify which bitmap to display
or you won't see anything. So we really create a bitmap like
this:
$id = $canvas->createBitmap(x, y, -bitmap => bitmap);
The other options available for
createBitmap are:
- -anchor => "center" | "n" | "e" | "s" | "w" | "ne" | "nw" | "se" | "sw"
-
The -anchor
option determines how the bitmap is placed on the Canvas relative to
the (x, y) coordinates indicated. The default for
-anchor is "center", which puts
the center of the image at the (x, y) coordinates. Using a single
cardinal direction (for example, "e") would place
the center of that edge at the (x, y) coordinates.
- -background => color
-
The -background option
specifies the color to use for all the 0 (zero) bitmap pixels. If you
don't specify a background color or use an empty string
(""), the 0 pixels will be transparent.
- -bitmap => bitmapname
-
You must
use the -bitmap option to tell the Canvas which
bitmap to display. You can use the built-in bitmaps (such as
'info' or 'warning') just as
you can with the Button widget, or you can specify a filename.
Remember, to specify a bitmap file, use an @ sign
in front of the filename.
- -foreground => color
-
The foreground color of a bitmap is the
opposite of the background color. (By definition, bitmaps can have
only two colors.) The -foreground option will
color all the 1 pixels with this color. The default for
-foreground is black.
- -tags => taglist
-
Use the -tags
option to assign tag names to a bitmap. The value associated with
-tags is an anonymous list of tag names; for
example:
$canvas->createBitmap(0,0, -bitmap => 'info',
-tags => ["info", "bitmap"]);
You don't need to use the list if you are only specifying one
tag name:
$canvas->createBitmap(0,0, -bitmap => 'info', -tags => "bitmap");
9.6.3. The Image Item
If we can create a bitmap on a Canvas, it makes sense that we can
create an image as well. We can do so with the
createImage method:
$id = $canvas->createImage(x, y, -image => image);
Again, you have to specify an image
to display or you won't see anything. The other options
available for createImage are:
- -anchor => "center" | "n" | "e" | "s" | "w" | "ne" | "nw" | "se" | "sw"
-
The -anchor
option for an image works the same as it does for a bitmap. The
-anchor option is how the image is positioned
around the (x, y) coordinates.
- -image => $image
-
The -image
option indicates which image to display. The image value is actually
a reference to an image created with the Photo or
Bitmap methods. (See Chapter 3, "Fonts"
for more information on how to specify an image file.)
- -tags => taglist
-
Use the -tags
option to assign tag names to an image. The value associated with
-tags is an anonymous list of tag names; for
example:
$canvas->createImage(0,0, -image => $imgptr,
-tags => ["image", "blue"]);
You don't need the list if you are specifying only one tag name:
$canvas->createImage(0,0, -image => $imgptr, -tags => "image");
9.6.4. The Line Item
The
createLine method can actually create multiple
connected lines, not just one. The first two coordinate sets you
supply create the first line, and any additional coordinates will
continue the line to that point:
$id = $canvas->createLine(0,0, 400,400); # creates one line
$id = $canvas->createLine(0,0, 400,400, -50, 240); # creates two lines
After the coordinates, you can specify any options and values you
wish to configure the line(s); the options and values are as follows:
- -arrow => "none" | "first" | "last" | "both"
-
Use the
-arrow option to place arrowheads at either end of
the line (or both). If you have more than one line in your
createLine method, only the first and/or last
point can be made into an arrow. If you want each line to have an
arrowhead, use multiple createLine statements.
- -arrowshape => [ dist1, dist2, dist3 ]
-
The
-arrowshape option applies only if you use the
-arrow option as well.
Specify the three distances by using an anonymous list such as this:
$canvas->createLine(10, 10, 200, -40, -arrow => "both",
-arrowshape => [ 20, 20, 20]);
Figure 9-4 shows what the
distance values mean.
Figure 9-4. Definition of arrowhead
- -capstyle => "butt" | "projecting" | "round"
-
Instead of
arrowheads, you can make the ends of the line have one of these
styles.
- -fill => color
-
The -fill option
is misnamed, because it isn't actually filling anything. The
line is simply drawn with this color instead of black.
- -joinstyle => "bevel" | "miter" | "round"
-
The
-joinstyle option affects how multiple lines are
joined together. If there is only one line created, this option has
no effect.
- -smooth => 1 | 0
-
If
-smooth has a value of 1, then, using Bezier
spline(s), the line(s) will be drawn as a curve. The first two lines
make the first spline, the second and third line make up the second
spline, and so on. To make a straight line, repeat the end points of
the desired straight line (or use createLine again
to make a separate line).
- -splinesteps => count
-
When you
use the -smooth option, the more
-splinesteps you use, the smoother the curve. To
find out how many steps create the desired effect, you'll have
to experiment with different values.
- -stipple => bitmap
-
To have the line drawn with a
bitmap pattern (1 values in the bitmap have color; 0 values are
transparent), use the -stipple option. The bitmap
can be a default bitmap name or a filename. The wider the line (see
-width), the more the stipple design will show up.
- -tags => taglist
-
When you create a line (or lines),
assign tag names to them using the -tags option.
The value associated with -tags is an anonymous
list of tag names; for example:
$canvas->createLine(0,0, 100,100, -tags => ["line", "blue"]);
You don't need to use a list if you are specifying only one tag
name:
$canvas->createLine(0,0, 100, 100, -tags =>
"line");
- -width => amount
-
You can use the
-width option to make the line(s) thicker.
Normally the line is drawn only 1 pixel wide. The amount can be any
valid screen distance (e.g., centimeters, inches).
9.6.5. The Oval Item
An
oval can be a circle if you draw it just right. To create a circle or
oval, use the createOval method and specify two
sets of points that indicate a rectangle (or square) in which to draw
the oval. Here is a simple example:
$id = $canvas->createOval(0,0, 50, 50); # creates a circle
$id = $canvas->createOval(0,0, 50, 100); # creates an oval
The options for the
oval will be familiar, so we'll just cover them briefly:
- -fill => color
-
Fills in the oval with the
specified color. This color is different than the outline color. By
default, the oval is not filled.
- -outline => color
-
The outline is the line drawn
around the outside of the circle. Normally, the outline is black, but
you can use the -outline option to change it. If
you make the outline and the fill color the same, the oval appears
solid.
- -stipple => bitmap
-
To fill the oval with a bitmap
pattern (1 values in the bitmap are colored; 0 values are
transparent), use the -stipple option. If the
-fill option isn't used,
-stipple has no effect.
-stipple takes a default bitmap name or a file
with a bitmap in it.
- -tags => taglist
-
When you create an oval, use the
-tags option to assign tag names to it. The value
associated with -tags is an anonymous list of tag
names; for example:
$canvas->createOval(0,0, 100,100, -tags => ["oval", "blue"]);
You don't need to use a list if you are specifying only one tag
name:
$canvas->createOval(0,0, 100, 100, -tags => "oval");
- -width => amount
-
The -width
option changes how wide the outline of the oval is drawn. The default
for -width is 1 pixel.
9.6.6. The Polygon Item
A
polygon is merely a bunch of lines where the first point is connected
to the last point automatically to create an enclosed area. The
createPolygon method requires at least three (x,
y) coordinate pairs. For instance, the following piece of code will
create a three-sided polygon:
$id = $canvas->createPolygon(1000,1000, 850,950, 30,40);
Additional (x, y) coordinate pairs can be specified as well; for
example:
$id = $canvas->createPolygon(1000,1000, 850,950, 30,40, 500,500);
The options you can specify with createPolygon are
the same as those you use with createLine:
-fill, -outline,
-smooth, -splinesteps,
-stipple, -tags, and
-width. Just remember that
createPolygon connects the first point to the last
point to enclose the area.
9.6.7. The Rectangle Item
As
if being able to create a rectangle using
createLine or createPolygon
weren't enough, we also have the
createRectangle method. It only takes two (x, y)
coordinate sets, which are the opposite corners of the rectangular
area:
$id = $canvas->createRectangle(10, 10, 50, 150);
Again, we have seen the options available
for createRectangle with the other
create methods: -fill,
-outline, -stipple,
-tags, and -width. Although
we've covered these options already, here are a few examples:
# A blue rectangle with black outline:
$canvas->createRectangle(10,10, 50, 150, -fill => 'blue');
# A blue rectangle with a thicker outline:
$canvas->createRectangle(10,10, 50, 150, -fill => 'blue', -width => 10);
9.6.8. The Text Item
Finally, an item type that doesn't have lines in it! You can
use the createText method to add text to a Canvas
widget. It requires an (x, y) coordinate pair, which determines where
you place the text in the Canvas and the text to be displayed:
$id = $canvas->createText(0,0, -text => "origin");
The -text option
is actually optional, but then you wouldn't see any text on the
screen. Because there is no point in that, we will assume that you
will always specify -text with a text value to
display. The other options available for text items are as follows:
- -anchor => "center" | "n" | "e" | "s" | "w" | "ne" | "nw" | "se" | "sw"
-
The -anchor
option determines where the text is placed in relation to the (x, y)
coordinate. The default is centered: the text will be centered over
that point no matter how large the piece of text is.
- -fill => color
-
The text is normally drawn in
black; you can use the -fill option to change
this. The name of this option doesn't make much sense when you
think about it in terms of text (normally our widgets use
-foreground to change the color of the text). For
example, -fill => 'blue' will draw blue text.
- -font => fontname
-
You can change the font for the
displayed text by using the -font option.
- -justify => "left" | "right" | "center"
-
If the displayed text has more than
one line, the -justify option will cause it to be
justified as specified.
- -stipple => bitmap
-
This option is a bit strange, but
here it is anyway. If you specify a bitmap name (or file) with the
-stipple option, the text will be drawn by using
the bitmap pattern. Most of the time, this will make the text
unreadable, so don't use it unless you're using a large
font.
- -tags => taglist
-
The
taglist is a single tag name or an
anonymous list of tag names to be assigned to the item.
- -text => string
-
This is not optional. The specified
string is displayed in the Canvas widget at the (x, y) coordinate.
- -width => amount
-
This is another misnamed option,
because it does not change the width of each text character. It
determines the maximum length of each line of text. If the text is
longer than this length, the line will automatically wrap to a second
line. The default value for amount is 0,
which will break lines only at newline characters. Lines are always
broken at spaces so words won't be cut in half.
The following options, discussed earlier,
work the same as they would for an Entry widget or a Text widget:
-insertbackground,
-insertborderwidth, -insertofftime,
-insertontime, -insertwidth,
-selectbackground,-selectborderwidth, and-selectforeground. See Chapter 5, "Label and Entry Widgets" and Chapter 8, "The Text, TextUndo,and ROText Widgets" for more
details.
9.6.8.1. Text item indexes
Methods that affect text items will
sometimes ask for an index value. Text indexes for the regular Text
widget were covered in Chapter 8, "The Text, TextUndo,and ROText Widgets", and the index
values for a Canvas text item are similar. The only difference is
that each item is considered only one line (even if it has
"\n" characters in it). Index values are as
follows:
- n
-
A number value. For example, 0 or 12. 0 is the first character, 1 is
the second, and so on.
- "end"
-
The character directly after the last one. Often used with the
insert method to add to the end of the string.
- "insert"
-
The character directly before the insertion cursor.
- "sel.first"
-
The first character of the selected text. Only valid if there is a
selection.
- "sel.last"
-
The last character of the selected text. Only valid if there is a
selection.
- "@x,y"
-
The character closest to the point (x,
y) of the Canvas (not screen coordinates).
9.6.8.2. Deleting characters
To
delete characters from within a text item, use the
dchars method:
$canvas->dchars(tag/id,
first [, last
]). Specify a tag or ID to match the
text item(s) and the index at which to start deleting. If the end
index isn't specified, all the characters to the end of the
string will be deleted (including any "\n"
characters).
9.6.8.3. Positioning the cursor
To
specifically place the blinking text cursor, use the
icursor method :
$canvas->icursor(tag/id,
index). The cursor will only
show up immediately if the specified item has the current keyboard
focus. You can still set the position of the cursor if it
doesn't, it just won't display until the item does get
the keyboard focus.
9.6.8.4. Index information
To find an
index based on another index, use the index
method. Here's an example:
$index = $canvas->index("textitem", "sel.first");
This returns the numerical index associated with the first selected
character in the text item. If more than one item matches the tag or
ID indicated (in this case, it's a tag named
"textitem"), then the first one found is used.
9.6.8.5. Adding text
To add more text to a text item, use the insert
method:
$canvas->insert(tag/id,
index,
string). The first argument
is the tag or ID, which can match multiple items. The second argument
is the index before which to insert the new string, and the last
argument is the actual string to insert into the text item.
9.6.8.6. Selecting text
There are several methods you can use to programmatically select
portions of the text. To clear the selection (any selection; there
are no tags or IDs sent with this command), use
$canvas->selectClear. To select a portion of
text, use selectFrom and
selectTo. The following two lines of code select
the text from beginning to end for the first item that matches the
tag "texttag":
$canvas->selectFrom("texttag", 0);
$canvas->selectTo("texttag", "end");
You can
use the selectAdjust method to add to the
selection: $canvas->selectAdjust("adjust",
tag/id,
index). To get the ID
of the item that currently has the selection in it, use $id
= $canvas->selectItem.
9.6.9. The Widget Item
You can put any type of widget inside a
Canvas—Buttons, Checkbuttons, Text widgets, or even another
Canvas widget (if you are a little crazy)—by using the
createWindow method. Before calling
createWindow, you must create the widget to put
into the Canvas. Here's an example:
$bttn = $canvas->Button(-text => "Button",
-command => sub { print "Button in Canvas\n"; });
$id = $canvas->createWindow(0, 0, -window => $bttn);
There are a few things you should note about this example (which is
fairly typical, except the subroutine associated with the Button
doesn't do anything useful):
-
The Button is a child of the Canvas widget. The Button could be a
child of an ancestor of the Canvas (the Button could be a child of
the MainWindow if the Canvas is also a child of the MainWindow).
However, the Button should not be a child of a different Toplevel
widget that has nothing to with the Canvas.
-
The createWindow method doesn't actually
create the widget; it just puts it in the Canvas. The Button is
placed at the specified coordinates inside the Canvas and has not
been placed on the screen with pack,
grid, or place.
-
The widget must be created before you call
createWindow.
-
You can click the Button and the callback associated with it will be
invoked, just as with any other Button.
-
When you create the widget, you can use any of that widget's
options to configure it. To continue configuring the widget, use the
reference to it (e.g., $bttn).
The following options, which you can use when you call
createWindow, are more like options you use with
pack than widget options:
- -anchor => "center" | "n" | "e" | "s" | "w" | "ne" | "nw" | "se" | "sw"
-
The widget will be placed at the
(x, y) coordinates according to the -anchor value.
The default is "center", which means that the
widget will have its center point placed on (x, y).
- -height => amount
-
The widget will be given this
height. If you don't use -height, the widget
will have the height it was created with (usually the natural size of
the widget).
- -tags => taglist
-
The
taglist associates a tag with the widget.
You can specify either a single tag string or an anonymous list of
tag names.
- -width => amount
-
The widget will be given this
width. If you don't use the -width option,
the widget will have the width it was created with (the natural size
of the widget).
- -window => $widget
-
This is a nonoptional option. If
you don't specify -window, there will be no
widget put in the Canvas. The $widget is a
reference to a widget item. You can create the widget beforehand or
inline as follows:
$canvas->createWindow(0,0, -window => $canvas->Button(-text => "Button",
-command => sub { print "Button!\"; }));
It makes sense to create the widget inline if you don't need to
do anything fancy with it.
9.6.10. The Grid Item
Perl/Tk has an
experimental grid item type that displays
dotted, dashed, or solid lines, in both the x and y dimensions. The
effect is reminiscent of old-fashioned graph paper.
Grid items cover the entire Canvas, but never enclose or overlap any
area and are not near any point, so you cannot search for them using
the closest, enclosed, or
overlapping attributes. In most other regards,
they behave like other Canvas item types. Currently, grids, like
window items, do not appear in PostScript output.
Grid items
are created like this:
$canvas->createGrid(x1, y1, x2, y2, ... );
x1 and y1
specify the origin of the basal grid cell, and
x2 and y2
specify its width and height, respectively; the cell is replicated
over the entire surface of the Canvas widget. By default, dots are
drawn at every grid intersection, unless the
-lines option is set true. When drawing lines,
dash specifications are honored.
This code generated Figure 9-5:
my $c = $mw->Canvas(qw/-width 300 -height 200/)->grid;
$c->configure("-scrollregion" => [0,0, 300, 200]);
$c->createGrid(0, 0, 10, 10);
$c->createGrid(0, 0, 50, 50, -lines => 1, -dash => '-.');
$c->createGrid(0, 0, 100, 100, -width => 3, -lines => 1);
One important note: grid
items remain invisible unless a scroll region is defined.
This may be construed as a bug, which is one reason why grids are
deemed experimental.
Figure 9-5. A canvas with three grid items
9.6.11. The Group Item
Perl/Tk sports a new Canvas item called a
group. A group item is actually a collection of
standard Canvas items that can be manipulated simultaneously. The
following code creates an oval and a rectangle, then groups them
together:
$one = $canvas->createOval(5, 0, 20, 30, -fill => 'blue');
$two = $canvas->createRectangle(0, 20, 50, 75, -fill => 'red');
$group = $canvas->createGroup([0, 0], -members => [$one, $two]);
$mw->update;
$mw->after(1000);
$canvas->move($group, 100, 100);
Figure 9-6 shows the outcome.
Figure 9-6. Before move
After a one-second delay, the group is moved to a new Canvas
coordinate, shown in Figure 9-7.
Figure 9-7. After move
Of course, sometimes you want to get to individual items within the
group, perhaps to configure a special attribute. The current idiom is
to iterate through the members of the group, like this:
foreach my $member ($canvas->itemcget($group, -members)) {
print "member=$member\n";
}
This example prints out the item ID for each member of the group, but
you can use the item IDs in an itemconfigure call.
| | | 9.5. Canvas Options | | 9.7. Configuring the Canvas Widget |
Copyright © 2002 O'Reilly & Associates. All rights reserved.
|