The WCK passes a draw object to the ui_handle_repair
and ui_handle_clear methods. This object provides an interface
to the underlying drawing library. By default, the WCK uses a
relatively simple drawing library, which lets you draw text, lines,
rectangles, and other 2D graphic elements to the screen.

To draw text, use the text method. To determine the width
and height of the text, you can use the textsize method. The
following example uses both methods to draw some right-aligned text in
the widget area:

Coordinates

The WCK coordinate system uses pixel coordinates, with (0, 0) in
the widget’s upper left corner. To specify a rectangle, four
coordinates are needed (left, top, right, bottom). To specify a
polygon, you need to specify at least three coordinate pairs (x0, y0,
x1, y1, x2, y2).

Note that coordinates must be given as ‘flattened’ Python
sequences; PIL’s [(x, y), (x, y), …] format is not supported.

Colors

The exact set of available color names is somewhat platform
dependent, but most english names are available. If you need more
control, use hexadecimal specifiers.

Pens

Pen objects are used to draw lines, as well as the outline of
shapes like rectangles and polygons.

To create a pen, pass in the pen color and an optional width to the
ui_pen factory method (note that this is a widget method, not a
method of the drawing object):

pen = self.ui_pen(color, width)

You can store the pen in the widget instance for later use, but you
cannot use a pen in other widgets than the one it was created for.

FIXME: implementation note: it may be time to drop
this restriction, and force the implementation to work around this
problem in platforms where this might be a real problem…

Brushes

Brush objects are used to fill the interior of shapes, such as
rectangles and polygons.

To create a brush, pass in the brush color to the ui_brush
factory method:

brush = self.ui_brush(color)

As with pens, you can store a brush for later use in the same
widget.

Fonts

Font objects are used to draw text in a widget. In the WCK drawing
interface, a font object represents both the actual font, and what
color to use to draw the text.

To create a font, pass in a font color and a font specifier to the
ui_font constructor:

font = self.ui_font(color, specifier)

As with pens and brushes, you can store a font object for later use
in the same widget, but you cannot use it in another widget.

The color argument is a color string, as described
above.

The font specifier argument is a Tkinter-style font
specifier, using the following syntax: “{family} size style…”, or
slight variations thereof. Some examples:

"Times""Arial 20 bold""{Trebuchet MS} 12""Textile 12"

The family part specifies what font to use. Common families
like Helvetica, Times, and Courier are supported
on all platforms (they’re mapped to native fonts where necessary).
What other families you can use depend on the WCK implementation, and
the fonts installed on the host computer.

You can leave out the braces if the family name doesn’t contain
whitespace, and doesn’t start with a digit. If omitted, the family
name defaults to Courier.

The size is given in points (defined as 1/72 inch). If
omitted, it defaults to 12 points. Note that the toolkit takes the
logical screen size into account when calculating the actual
font size. On low resolution screens, this means that a 12-point font
is usually larger than 12/72 inches.

The style attributes can be any combination of
normal, bold, roman (upright), italic,
underline, and overstrike, separated by whitespace. If
omitted, it defaults to the default style setting for that family;
usually normal roman.

For Tkinter compatibility, you can also pass in a font tuple:
(“family”, size, style…). In this case, there should be no braces
around the family name. You can also leave out the size and/or the
style arguments. The defaults are the same as for the string
syntax.

Object Caching

Some WCK implementations may cache pens, brushes, and font objects
to speed up object construction. This means that if you pass in the
same arguments to an object factory, you will most likely get back
exactly the same object.

While caching can simplify code (you can rely on the cache, instead
of storing lots of objects in instance variables), it can cause
problems for widgets that use lots of objects during their lifetime.
If you need to clear the cache, call the ui_purge method.

Note: The object cache was introduced in release
1.1. Earlier versions do not use an object cache.

The line method takes a single pen object, created by
the ui_pen method.

The rectangle, polygon and ellipse methods
take brush objects, created by ui_brush, and use it to
fill the given region. These methods can also take an optional pen
object, which is used to draw an outline.

In addition to the basic 2D drawing primities, the WCK allows you
to display images in a widget. The WCK image support consists of two
similar mechanisms: pixmaps and images.

A pixmap is an ordinary raster image, with the same resolution and
format as the display. You can use the drawing interface to draw in a
pixmap, just like you can draw on the screen.

The ui_pixmap method creates a pixmap object:

pixmap = self.ui_pixmap(width, height)

In an X window system running across the network, the pixmap is
stored in the terminal (the X server). On other platforms, the pixmap
may be stored in an off-screen portion of the display memory. In
either case, copying pixels from a pixmap to the screen is a very fast
operation.

An image is similar to a pixmap, but does not necessarily have the
same format as the display. Images may be stored in client memory
instead of display memory, and copying may be less efficient than for
pixmaps. Image objects are used to import raster images from external
sources; you cannot use them for drawing.

The ui_image method creates an image object:

image = self.ui_image(source)

In the Tkinter version, the source object can be either a Tkinter
BitmapImage or PhotoImage (or a compatible object, such
as a PIL ImageTk.PhotoImage object), or a PIL image memory.
WCK 1.1 also allows you to create an image by specifing a PIL-compatible
mode, a size tuple, and the pixel data as a string.

You can use the paste operation to copy an image or a pixmap
into a window. The paste method is similar to the same method
in PIL, and takes a source image object, and an optional target offset
or target rectangle:

draw.paste(image, xy)

The image object can be either an image (created with
ui_image) or a pixmap (created with ui_pixmap). Note
that the image is pasted into the drawing area, not the other way
around.

The target can be a 2-tuple offset (upper left corner) or a 4-tuple
rectangle. If omitted, the target defaults to (0, 0).

By default, the WCK framework clears the widget background before
it calls the ui_handle_repair method. To clear the background,
it simply fills it with the background color (as given by the
background option).

You can modify this behavior by overriding the
ui_handle_clear method. For example, if the repair method
always redraws the entire widget, you can save a little time (and
reduce flicker) by adding an empty ui_handle_clear method:

The checkerboard example showed how you can eliminate flicker for
widgets that cover their entire surface with non-overlapping elements
(such as the checkerboard tiles).

But figuring out how to avoid overlaps isn’t always that easy. For
example, consider something as simple as adding a red piece to the
checkerboard. Drawing the piece is trivial; just call the
ellipse method with a suitable brush:

But since you draw the background first, it may appear on the
screen very briefly, before the piece is drawn. Create a larger
board, and add more pieces, and the flicker may become really
annoying. And unfortunately, it’s not obvious how to calculate the
area not covered by the ellipse. You could probably approximate the
piece with a polygon, and use the same coordinates to draw a polygon
covering only background, but that’s a lot of work.

The WCK provides a much simpler solution: create an off-screen
pixmap, draw into the pixmap instead of the widget, and copy the
pixmap to the screen when everything is drawn.

To illustrate this approach, here’s a much simplified version of
Tkinter’s Canvas widget. The SimpleCanvas widget maintains an
ordered list of graphic elements (the stack), and draws it to the
display. To minimize flicker, the repair method draws into a pixmap,
which is then copied to the screen.

The widget provides a simple list-like interface; you can add new
items using append and insert, and remove existing items
using delete.

The following sample creates a canvas widget, and adds three
rectangles to it. It also installs a Tkinter event handler that lets
you move the second item (the blue rectangle), by pressing the mouse
button over the widget and moving the mouse around.

Using the ui_doublebuffer flag

Full widget animation of this kind is pretty common, so the WCK
provides an easier way to draw via an extra pixmap; just set the
ui_doublebuffer class attribute to a true value, and leave
the rest to the framework: