Racket: using events in a frame% window
I'm learning Racket (formerly PLT Scheme, a LISP dialect) and try to discover how to handle events different than paint-callback
(maybe it's not even one).
I hoped a lot from this part of the doc but on-char
and on-event
seem to do nothing that could interest me (or nothing at all).
Plus, I don't understand eventspaces, queue-callback and their uses. An example would be a cool thing! I'll be thankful to the nice man who'll write me one :).
Here's my code:
(define game (new frame%))
(define gameLay (class canvas% (super-new)))
(new gameLay
[parent game]
[paint-callback (λ (canvas dc) #|draw things|#)])
I want to use something like "on-mouse-click-left" (which doesn't exist) the way I use "paint-callback" but I think I need to add steps (I've read about eventspaces etc.). I know it doesn't work but here's the hypothetical code I'm searching for:
(new gameLay
[parent game]
[paint-callback (λ (canvas dc) #|draw things|#)]
开发者_运维问答 [on-mouse-click-left (λ (canvas dc) #|do other things|#)])
Here's a little program using canvases and keyboard events. Once you've pressed an arrow key, the canvas shows the last one you pressed.
#lang racket/gui
(define game-canvas%
(class canvas%
(inherit get-width get-height refresh)
;; direction : one of #f, 'left, 'right, 'up, 'down
(define direction #f)
(define/override (on-char ke)
(case (send ke get-key-code)
[(left right up down)
(set! direction (send ke get-key-code))
(refresh)]
[else (void)]))
(define/private (my-paint-callback self dc)
(let ([w (get-width)]
[h (get-height)])
(when direction
(let ([dir-text (format "going ~a" direction)])
(let-values ([(tw th _ta _td)
(send dc get-text-extent dir-text)])
(send dc draw-text
dir-text
(max 0 (/ (- w tw) 2))
(max 0 (/ (- h th) 2))))))))
(super-new (paint-callback (lambda (c dc) (my-paint-callback c dc))))))
(define game-frame (new frame% (label "game") (width 600) (height 400)))
(define game-canvas (new game-canvas% (parent game-frame)))
(send game-frame show #t)
Every frame has an eventspace that manages event dispatching. The on-char
method is an event handler; it is run in the eventspace handler thread. No more events will be processed until your on-char
method finishes. So if you want to do something complicated, you might want to create a separate thread and do the computation over there. One simple way to do that is to make another eventspace, one that doesn't handle events for any frame, but that handles "events" you send it using queue-callback
. For example, replace the definition of on-char
above with this:
(define aux-eventspace (make-eventspace))
(define/override (on-char ke)
(parameterize ((current-eventspace aux-eventspace))
(queue-callback
(lambda ()
(case (send ke get-key-code)
((left right up down)
(set! direction (send ke get-key-code))
(refresh))
(else (void)))))))
The function given to queue-callback
is run in a separate thread. You can insert some printouts, delays, or whatever to convince yourself that the main eventspace can still process events while the other one handles your callback.
精彩评论