Ракетка: использование событий в рамке% окна - PullRequest
8 голосов
/ 03 сентября 2011

Я изучаю Ракетка (ранее PLT Scheme , диалект LISP) и пытаюсь узнать, как обрабатывать события, отличные от paint-callback (возможно, это даже не одно).

Я очень надеялся от этой части документа , но on-char и on-event, кажется, не делают ничего, что могло бы меня заинтересовать (или вообще ничего).

Кроме того, я не понимаю пространства событий, очереди вызовов и их использования.Примером будет классная вещь!Я буду благодарен хорошему человеку, который напишет мне один:).

Вот мой код:

(define game (new frame%))

(define gameLay (class canvas% (super-new)))

(new gameLay
     [parent game]
     [paint-callback (λ (canvas dc) #|draw things|#)])

Я хочу использовать что-то вроде "on-mouse-click-оставил "(которого не существует) способ, которым я использую" paint-callback ", но я думаю, что мне нужно добавить шаги (я читал о пространствах событий и т. д.).Я знаю, что это не работает, но вот гипотетический код, который я ищу:

(new gameLay
     [parent game]
     [paint-callback (λ (canvas dc) #|draw things|#)]
     [on-mouse-click-left (λ (canvas dc) #|do other things|#)])

1 Ответ

12 голосов
/ 03 сентября 2011

Вот небольшая программа, использующая холсты и события клавиатуры. После нажатия клавиши со стрелкой на холсте отображается последняя нажатая клавиша.

#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, запускается в отдельном потоке. Вы можете вставить некоторые распечатки, задержки или что-то еще, чтобы убедиться, что основное пространство событий все еще может обрабатывать события, в то время как другое обрабатывает ваш обратный вызов.

...