by M. Douglas Williams
m.douglas.williams at gmail.com
This library provides an animates-canvas% class that specializes the MrEd class canvas% to provide a simple double-buffered animation capability in PLT Scheme. A simple demonstration program is also provided.
Everything in this library is exported by a simgle module:
This section assumes you are familiar with the canvas% class.
An animated canvas uses two bitmaps to provide a double-buffered animation capability. This is implemented by a new class that specializes the canvas% class. At any specific time, one bitmap, the background bitmap, is being used for all drawing operations and the other bitmap, the foreground bitmap, is being used to paint the canvas.
The swap-bitmaps method is used to swap the background and foreground bitmaps. When the bitmaps are swapped, the contents of the new foreground bitmap – the old background bitmap – is displayed on the canvas. The new background bitmap – the old foreground bitmap – is automatically cleared unless specifically prevented by the 'no-autoclear style option.
The device context returned by the animated canvases’s get-dc method is the device context of the background bitmap. This value is not valid across calls to swap-bitmaps. Therefore, it is important to re-retrieve, via get-dc, the device context across bitmap swaps.
The animated canvas also supports resizing on the canvas, which automatically resizes the background buffer after the bitmaps are swapped.
An object is a specialized canvas% object for animated drawings.
Most of the following description is from the GUI: PLT Graphics Toolkit reference manual with additions as noted for . Changes that are specific to the are in bold face.
→ (is-a?/c )
'vscroll 'hscroll 'resize-corner
'gl 'no-autoclear 'transparent
enabled : any/c = #t
vert-margin : (integer-in 0 1000) = 0
horiz-margin : (integer-in 0 1000) = 0
min-width : (integer-in 0 10000) = graphical-minimum-width
min-height : (integer-in 0 10000) = graphical-minimum-height
stretchable-width : any/c = #t
stretchable-height : any/c = #t
The style argument indicates one or more of the following styles:
'border – gives the canvas a thin border
'control-border – gives the canvas a border that is like a text-field% control
'combo – gives the canvas a combo button that is like a combo-field% control; this style is intended for use with 'control-border and not with 'hscroll or 'vscroll
'hscroll – enables horizontal scrolling (initially visible but inactive)
'vscroll – enables vertical scrolling (initially visible but inactive)
'resize-corner – leaves room for a resize control at the canvas’s bottom right when only one scrollbar is visible
'gl – obsolete (every canvas is an OpenGL context where supported)
'no-autoclear – prevents automatic erasing of the background bitmap after calls to
'transparent – ignored for an animated canvas
'no-focus – prevents the canvas from accepting the keyboard focus when the canvas is clicked, or when the focus method is called
'deleted – creates the canvas as initially hidden and without affecting parent’s geometry; the canvas can be made active later by calling parent’s add-child method
The 'hscroll and 'vscroll styles create a canvas with an initially inactive scrollbar. The scrollbars are activated with either init-manual-scrollbars or init-auto-scrollbars, and they can be hidden and re-shown with show-scrollbars.
The paint-callback argument is ignored for an animated canvas.
The label argument names the canvas for get-label, but it is not displayed with the canvas.
Returns the device context of the background bitmap. This value changes across calls to swap-bitmaps.
Swaps the background and foreground bitmaps, displays the new foreground bitmap, and clears the new background bitmap (unless explicitly requested not to do so).
This section contains an example animated graphics program that uses the class.
; Lines animated canvas example.
; Draws moving line similar to those in the Qix video game.
(x1 y1 x2 y2))
(x1 y1 x-dot1 y-dot1 x2 y2 x-dot2 y-dot2 color segments)
(define max-segments 12)
(define (draw-qix the-qix)
(define (draw-segment dc x1 y1 x2 y2 color)
(send dc set-pen color 0 'solid)
(send dc draw-line x1 y1 x2 y2))
(qix-segment-x1 segment) (qix-segment-y1 segment)
(qix-segment-x2 segment) (qix-segment-y2 segment)
(send canvas swap-bitmaps)))
(define (move-qix the-qix)
(define (update-position-x x x-dot)
(values x x-dot))
(define (update-position-y y y-dot)
(values y y-dot))
; Update the qix position
(let-values (((x x-dot)(update-position-x (qix-x1 qix) (qix-x-dot1 qix))))
(set-qix-x1! qix x)
(set-qix-x-dot1! qix x-dot))
(let-values (((y y-dot)(update-position-y (qix-y1 qix) (qix-y-dot1 qix))))
(set-qix-y1! qix y)
(set-qix-y-dot1! qix y-dot))
(let-values (((x x-dot)(update-position-x (qix-x2 qix) (qix-x-dot2 qix))))
(set-qix-x2! qix x)
(set-qix-x-dot2! qix x-dot))
(let-values (((y y-dot)(update-position-y (qix-y2 qix) (qix-y-dot2 qix))))
(set-qix-y2! qix y)
(set-qix-y-dot2! qix y-dot))
; Add a new segment to the segment list
(set-qix-segments! qix (append (qix-segments qix)
(qix-x1 qix) (qix-y1 qix)
(qix-x2 qix) (qix-y2 qix)))))
; Remove old segments
(set-qix-segments! qix (cdr (qix-segments qix)))))
(define break? #f)
(define (main n-qix)
(send run-button enable #f)
(set! break? #f)
(let loop ()
(unless break? (loop)))))
(send run-button enable #t)
; GUI elements
(alignment '(right center))
(callback (lambda (b e)
(main (send slider get-value))))))
(callback (lambda (b e)
(set! break? #t)))))
("Number of qix" 1 100 frame)
(min-width 800) (min-height 600)))
(send frame show #t)