Вот небольшая программа, использующая холсты и события клавиатуры. После нажатия клавиши со стрелкой на холсте отображается последняя нажатая клавиша.
#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)
Каждый кадр имеет пространство событий, которое управляет отправкой событий. Метод on-char
является обработчиком событий; он запускается в потоке обработчика событий. Больше событий не будут обрабатываться, пока ваш on-char
метод не завершится. Поэтому, если вы хотите сделать что-то сложное, вы можете создать отдельный поток и выполнить там вычисления. Один простой способ сделать это - создать другое пространство событий, которое не обрабатывает события для какого-либо кадра, но обрабатывает «события», которые вы отправляете, используя queue-callback
. Например, замените приведенное выше определение on-char
следующим:
(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)))))))
Функция, заданная для queue-callback
, запускается в отдельном потоке. Вы можете вставить некоторые распечатки, задержки или что-то еще, чтобы убедиться, что основное пространство событий все еще может обрабатывать события, в то время как другое обрабатывает ваш обратный вызов.