[racket-dev] try the GRacket2 branch

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Nov 1 19:15:17 EDT 2010

At Mon, 1 Nov 2010 10:33:10 -0600, Doug Williams wrote:
> I'll test it this evening when I am back home.
> The animated-canvas class actually keeps two bitmaps - one for painting from
> and one for drawing to. The swap-bitmaps methods swaps those and repaints
> the canvas. I'm not sure which of those the new canvas backing store would
> replace.

If I understand, then it replaces both. In GRacket2, call
`suspend-flush' before clearing the canvas to redraw, and call
`resume-flush' followed by `flush' at the point where you formerly
swapped the bitmaps.

The program below illustrates. When you run it, you should see color
bars move slowly to the left. The drawing is intentionally slow, and if
you set `sync?' to #f, it will flicker horribly. (Of course, you'll
need the latest gr2 for the example to work right.)

GRacket1 doesn't give you much control over the timing of canvas
refresh. You could only say "please refresh", and sometime later
`on-paint' would be called --- so an animation canvas needed to keep a
bitmap for the current display state to respond to those `on-paint'
calls. Meanwhile, you could draw into the other bitmap for the next

GRacket2 gives you more control, in a sense. If a canvas is in
suspended-flush mode, then `resume-flush', `flush', `suspend-flush'
effectively moves the current state of the canvas onto the screen, and
then you can immediately start drawing again for the next scene.

On some platforms, it's possible to expose the state of a
flush-suspended canvas. When running the example below under Windows,
if you drag another window over the one with the bars, then you can see
intermediate states that would not otherwise be flushed. Similarly, if
you try that with most window managers under X, the canvas just stays
unrefreshed until it is flushed. In those cases, a buffer bitmap could
provide better results; if drawing takes a *very* long time and you
expect users to manipulate the surrounding GUI meanwhile, then a pair
of bitmaps still may be the way to go. My guess is that your uses of an
animation canvas will work well by just controlling flushes.

#lang racket/gui

(define SIZE 600)

(define f (new frame%
               [label "Color Bars"]
               [width SIZE]
               [height SIZE]))

(define c (new canvas% [parent f]))

(send f show #t)

(define sync? #t)

(define (start-drawing dc)
  (when sync?
    (send dc suspend-flush)))

(define (end-drawing dc)
  (when sync?
    (send dc resume-flush)
    (send dc flush)))

(define (go)
  (let ([dc (send c get-dc)])
    (for ([d (in-naturals)])
      (start-drawing dc)
      (send dc erase)
      ;; Draw somthing slow that changes with d
      (for ([n (in-range 0 SIZE)])
        (send dc set-pen 
              (make-object color% 
                           (remainder (+ n d) 256)
                           (remainder (* 2 (+ n d)) 256)
                           (remainder (* 3 (+ n d)) 256))
        (send dc draw-line n 0 n SIZE))
      (end-drawing dc))))

(thread go)

Posted on the dev mailing list.