以编程方式关闭由 `racket/gui` 生成的 window(停止 `timer%`)

Programmatically close a window made with `racket/gui` (to stop a `timer%`)

使用 racket/gui 运行 的球拍程序,直到所有 windows 都关闭。这使得编写如下程序变得容易:

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

现在程序将继续运行直到window关闭。

但是,有时以编程方式关闭 window 是有意义的,例如,如果我想要一个将关闭 window 并在倒计时结束后结束的倒计时。

据我所知,'close' a window 的唯一方法是 show 方法:

(send window show #f)

然而,这只会阻止显示 window,但不会真正关闭 window。通常,这就足够了,程序会退出,如本例所示:

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

但是,如果程序有定时器,则直到定时器结束后程序才会退出。您可以在 window on-close 中设置回调,但这只会在 window 实际关闭时调用,而不是在它被 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)

那么,有没有办法找出 window 何时被隐藏(通过 show)函数或以编程方式关闭 window?如果两者都不是,重写 show 方法来停止计时器是不是一个坏主意?

既然你是 subclassing frame% class 无论如何,你可以覆盖 show 方法1 到每当 window 关闭时停止计时器。 (如果这对您很重要,请记得在 window 重新打开时重新启动它。)

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

使您的整体 class 看起来像:

#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的时候似乎并不总是运行打电话。