2017-02-25 122 views
0

我想使用以下代码在画布上显示图像列表。但是,会出现一个空框架,直到整个'for'循环运行,才会显示图像,然后在框架中显示最终效果。动画画布上的图像列表

#lang racket/gui 
(require 2htdp/image) 

(define frame (new frame% 
        [label "Example"] 
        [width 500] 
        [height 500])) 

(send frame show #t) 
; (sleep 1) ; tried this to allow time for frame to show properly; does not help; 

(new canvas% [parent frame] 
    [paint-callback 
     (lambda (canvas dc) 
     (for ((i imglist))  ; imglist is a list of images to be displayed @ 1/second. 
      (send dc clear) 
      (send dc draw-bitmap 
        (image->bitmap i) 
        20 20) 
      ; (send dc flush)  ; this statement also does not help; 
      (sleep 1)    ; to show animation effect from list of images; 
     ))]) 

的图像 - >位功能是:;来源:https://lists.racket-lang.org/users/archive/2014-December/065110.html

(define (image->bitmap image) 
    (let* ([width (image-width image)] 
     [height (image-height image)] 
     [bm (make-bitmap width height)] 
     [dc (send bm make-dc)]) 
    (send dc clear) 
    (send image draw dc 0 0 0 0 width height 0 0 #f) 
    bm)) 

在哪里的问题,怎么能解决呢?

回答

1

paint-callback是为了快速更新画布,然后返回。 当它返回时,系统知道画布已更新。

一种方法来做你想做的:1)引入一个参数来保存当前显示的图像。 2)使paint-callback绘制当前图像。 3)制作一个单独的线程,每秒更改当前图像。

注意:下面我在image->bitmap的宽度和高度上加了+1。圆的边缘被切断。

#lang racket/gui 
(require 2htdp/image) 

(define images (list (circle 30 "outline" "red") 
        (circle 20 "outline" "red") 
        (circle 10 "outline" "red") 
        (circle 5 "outline" "red"))) 

(define current-image (make-parameter (first images))) 

(define (image->bitmap image) 
    (let* ([width (+ (image-width image) 1)] 
     [height (+ (image-height image) 1)] 
     [bm  (make-bitmap width height)] 
     [dc  (send bm make-dc)]) 
    (send dc clear) 
    (send image draw dc 0 0 0 0 width height 0 0 #f) 
    bm)) 

(define frame (new frame% 
        [label "Example"] 
        [width 500] 
        [height 500])) 

(define canvas (new canvas% [parent frame] 
        [paint-callback 
        (lambda (canvas dc) 
         (send dc clear) 
         (send dc draw-bitmap (image->bitmap (current-image)) 20 20))])) 

(send frame show #t) 

(thread (λ() 
      (let loop ([is images]) 
      (cond 
       [(null? is) (loop images)] 
       [else  (current-image (first is)) 
          (send canvas on-paint) 
          (sleep 1) 
          (loop (rest is))])))) 
+0

是的,它工作得很好。我发现我也可以用“(发送canvas get-dc)”来获取dc对象,然后在无限循环中对其进行绘制位图,但是框架关闭按钮不起作用,并且该过程必须从DrRacket IDE。使用线程的解决方案没有这样的问题。 – rnso

+0

我已经添加了这个作为回答,以清楚地显示它。 – rnso

0

以下工作:

(define images (list (circle 30 "outline" "red") 
        (circle 20 "outline" "red") 
        (circle 10 "outline" "red") 
        (circle 5 "outline" "red"))) 

(define (image->bitmap image) 
    (let* ([width (image-width image)] 
     [height (image-height image)] 
     [bm (make-bitmap width height)] 
     [dc (send bm make-dc)]) 
    (send dc clear) 
    (send image draw dc 0 0 0 0 width height 0 0 #f) 
    bm)) 

(define frame (new frame% [label "Frame"] [width 300] [height 300])) 
(define canvas (new canvas% [parent frame])) 
(define dc (send canvas get-dc)) 

(send frame show #t) 
(sleep/yield 1) 

(let loop() 
    (for ((i images)) 
    (send dc clear) 
    (send dc draw-bitmap 
      (image->bitmap i) 
      20 20) 
    (sleep 0.5)) 
    (loop)) 

然而,帧显示的动画并不接近,但必须从IDE停止。