What is the proper way to close a dialog box?

What is the proper way to close a dialog box?

I admit I haven't read everything in the GUI library yet and I'm trying to learn as I go, but I feel like I must be overcomplicating something here. I looked at the code for get-text-from-user and when the time comes to close the dialog it simply does (send dlg show #f) I feel like there should be a difference between "hide this thing" and "it's okay to garbage collect this thing".

I have the following code, which I was expecting would:

  1. Show a dialog box with text field, 'Ok', and 'Cancel' buttons
  2. Wait until one of the buttons is clicked
  3. Put the value of the field (or #f) onto an async channel
  4. Close the dialog

It does all of that except for the 'close the dialog' part, which makes me think that on-close is a thing that is used by the close process and will not actually trigger the close process. What is the right way to do it?

#lang racket/gui

(require racket/async-channel)

(define ch (make-async-channel))

; Create a dialog
(define dialog (instantiate dialog% ("Example")))

; Add a text field to the dialog
(define txt-field
  (new text-field% [parent dialog] [label "Your name"]))

; Add a horizontal panel to the dialog, with centering for buttons
(define panel (new horizontal-panel% [parent dialog]
                   [alignment '(center center)]))

; Add Cancel and Ok buttons to the horizontal panel
(new button%
     [parent panel]
     [label "Cancel"]
     [callback (λ (btn ctl-evt)
                 (displayln (format "callback for 'Cancel'. btn: ~v. ctl-evt: ~v" btn ctl-evt))
                 (async-channel-put ch #f)
                 (send dialog on-close))
               ])
(new button%
     [parent panel]
     [label "Ok"]
     [callback (λ (btn ctl-evt)
                 (displayln (format "callback for 'Ok'. btn: ~v. ctl-evt: ~v" btn ctl-evt))
                 (async-channel-put ch (send txt-field get-value))
                 (send dialog on-close))])

(when (system-position-ok-before-cancel?)
  (send panel change-children reverse))

(thread
 (thunk
  (let loop ()
    (displayln (sync ch))
    (loop)))) 

; Show the dialog
(send dialog show #t)
1 Like

https://docs.racket-lang.org/gui/top-level-window___.html#%28meth._%28%28%28lib._mred%2Fmain..rkt%29._top-level-window~3c~25~3e%29._on-close%29%29

The on-close method is more like a cleanup-handler just before the dialog is closed.

I have an example of a mixin which closes a dialog, though: https://github.com/benknoble/frosthaven-manager/blob/main/gui/mixins.rkt (well, really it passes a procedure to a callback; the procedure is used to close the dialog). Effectively it is

(when (… can-close?)
(… on-close)
(… show #f))
1 Like

As I understand it, a window receives on-close when it is about to close.
But sending the message on-close to the window doesn't make the window close.

I would use (send dlg show #f) as you suggest, followed by a strategically placed (set! dlg #f).
Eventually the garbage collector will reclaim the resources used by the dialog.

I belive the show/hide mechanism is in place to make it more efficient to "reuse" windows.

1 Like