问题
Racket programs that use racket/gui
run until all of the windows are closed. This makes it easy to write a program like:
#lang racket/gui
(define window (new frame% [label "Hello"] [width 100] [height 100]))
(send window show #t)
And now the program will continue to run until the window is closed.
However, it sometimes makes sense to close a window programmatically, for example, if I want a countdown that will close the window and finish after the countdown is done.
As far as I can tell though, the only way to 'close' a window is the show
method:
(send window show #f)
This however only stops the window from being displayed, but does not actually close the window. Normally, this is good enough and the program exits, like in this example:
#lang racket/gui
(define window (new frame% [label "hello"]))
(send window show #f)
However, if the program has a timer, it will not exit until the timer finishes. You can set a callback in the window on-close
, but this is only called when the window is actually closed, not when its hidden with show
. For example, this program will not get stuck:
#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)
So, is there a way to either figure out when a window is hidden (via the show
) function or programmatically close the window? If neither is the case, is overwriting the show
method to stop the timer myself a bad idea?
回答1:
Since you are subclassing the frame%
class anyway, you can override the show method1 to stop the timer whenever the window is closed. (Do remember to restart it when the window reopens if that is important to you.)
(define/override (show show?)
(unless show?
(send timer stop))
(super show show?))
Making your overall class look something like:
#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)
Now your program will terminate.
1There is a on-superwindow-show method, but it does not seem to always run when show
is called.
来源:https://stackoverflow.com/questions/43877936/programmatically-close-a-window-made-with-racket-gui-to-stop-a-timer