[plt-scheme] MrEd - Animated canvas

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Tue Mar 6 16:54:40 EST 2007

At Tue, 06 Mar 2007 13:25:13 -0800, "Laurent" wrote:
> While seeking a little bit I saw that a double buffer had to be used,
> but I do not know how that goes. Somebody could it explain me how to
> simply carry out an animation without flutter in scheme ?
> [...]
> (define canvas_1 (new canvas% (parent vpanel_2)
>                       (min-width 400)
>                       (style '(border))
>                       (paint-callback (lambda (obj dc)
>                                         (send dc draw-rounded-
> rectangle
> CURSOR_POSITION 570 150 15 5)
>                                         ))))

Implement the buffer using bitmap%, and draw into it using bitmap-dc%.
Then draw the bitmap to the canvas using `draw-bitmap'.

One tricky part is creating a bitmap of the right size. Here's a bit of
code to help manage an offscreen bitmap given, a canvas:

 (define offscreen-w 0)
 (define offscreen-h 0)
 (define offscreen-bm #f)
 (define offscreen-dc (make-object bitmap-dc%))

 (define (reset-offscreen! canvas)
   ;; Get the size of the canvas's drawing area:
   (let-values ([(w h) (send canvas get-client-size)])
     ;; If the bitmap isn't the right size, create a new one:
     (unless (and (= offscreen-w w)
                  (= offscreen-h h))
       (set! offscreen-w w)
       (set! offscreen-h h)
       (set! offscreen-bm (make-object bitmap% w h))
       (send offscreen-dc set-bitmap offscreen-bm))))

Here's how it would be used in your example. Note that I added the
'no-autoclear style flag for the canvas% instance (otherwise a flicker
persists), and I added an explicit call to the `clear' method of the
offscreen drawing context (because the drawing area is no longer
automatically cleared):

 (define canvas_1 
   (new canvas% (parent vpanel_2)
        (min-width 400)
        (style '(border no-autoclear))
         (lambda (canvas dc)
           ;; Make sure the buffer is the right size:
           (reset-offscreen! canvas)
           ;; Draw the picture offscreen:
           (send offscreen-dc clear)
           (send offscreen-dc draw-rounded-rectangle 
                 CURSOR_POSITION 570 150 15 5)
           ;; Copy the picture onto the screen:
           (send dc draw-bitmap offscreen-bm 0 0)))))


Posted on the users mailing list.