Программно закрыть окно, созданное с помощью `racket/gui` (чтобы остановить `таймер%`)

Программы Racket, использующие racket/gui, работают до тех пор, пока не будут закрыты все окна. Это упрощает написание программы вида:

#lang racket/gui
(define window (new frame% [label "Hello"] [width 100] [height 100]))
(send window show #t)

И теперь программа будет работать до тех пор, пока окно не будет закрыто.

Однако иногда имеет смысл закрыть окно программно, например, если мне нужен обратный отсчет, который закроет окно и завершится после завершения обратного отсчета.

Насколько я могу судить, единственный способ "закрыть" окно - это метод show:

(send window show #f)

Однако это только останавливает отображение окна, но фактически не закрывает окно. Обычно этого достаточно, и программа завершает работу, как в этом примере:

#lang racket/gui
(define window (new frame% [label "hello"]))
(send window show #f)

Однако, если программа имеет таймер, она не завершится, пока таймер не завершит работу. Вы можете установить обратный вызов в окне on-close, но он вызывается только тогда, когда окно фактически закрыто, а не когда оно скрыто с помощью show. Например, эта программа не застрянет:

#lang racket/gui
(define window
  (new (class frame%
         (super-new [label "hello"])
         (define timer
           (new timer%
                [interval 1000]
                [notify-callback (λ x (displayln "ding"))]))
         (define/augment (on-close)
           (send timer stop)))))

(send window show #f)

Итак, есть ли способ выяснить, когда окно скрыто (через функцию show), или программно закрыть окно? Если это не так, является ли перезапись метода show, чтобы остановить таймер, плохой идеей?


person Leif Andersen    schedule 09.05.2017    source источник


Ответы (1)


Поскольку вы в любом случае создаете подкласс класса frame%, вы можете переопределить show метод1, чтобы остановить таймер всякий раз, когда окно закрыто. (Не забудьте перезапустить его, когда окно снова откроется, если это важно для вас.)

(define/override (show show?)
  (unless show?
    (send timer stop))
  (super show show?))

Чтобы ваш общий класс выглядел примерно так:

#lang racket/gui
(define window
  (new (class frame%
         (super-new [label "hello"])
         (define timer
           (new timer%
                [interval 1000]
                [notify-callback (λ x (displayln "ding"))]))
         (define/augment (on-close)
           (send timer stop))
         (define/override (show show?)
           (unless show?
             (send timer stop))
           (super show show?)))))

(send window show #f)

Теперь ваша программа завершится.

1Есть on-superwindow-show, но он работает не всегда запускается при вызове show.

person Leif Andersen    schedule 09.05.2017