[racket] Changing the menu items in a combo-field%

From: Kieron Hardy (kieron.hardy at gmail.com)
Date: Wed Oct 3 17:24:10 EDT 2012

Hi all,

I only did a quick search, but couldn't find an example of how to use a
combo-field%, in particular how to change the values it displays in its
drop-down list. I worked one up and post it here in case it is useful to

The combo-field% is extended (sub-classed) with the method update-choices,
that is passed the list of strings to use for the labels of the new menu
items that replace the old (existing) menu items. For the sake of this
example, the list of strings to use for the choices are stored in a limited
depth stack. Values are stored to the top of the stack from the text entry
field of the combo-field% via the callback for the 'add' button%.

I would appreciate any comments as to improvements that I could make. In
particular I'm uneasy about removing all the items from the popup menu and
then adding a whole new set of items. I feel like I should be reusing
existing menu items rather than doing all that creating and destroying.




#lang racket/base

(require racket/gui)

(define max-items 10)
(define max-item-index (sub1 max-items))

(define pop-item-to-top? #t)
(define allow-duplicate-items? #f)

; model a small stack of strings, 10 deep, new items are pushed at the
(define small-stack
  (new (class object%

         (define my-list '())

         (define/public (clear)
           (set! my-list '()))

         (define/public (add-item i)
           (if pop-item-to-top?
             ; if item is in the stack, remove it from the stack and push a
new copy to the top
             (let ([new-list (remove i my-list string=?)])
               (set! my-list (cons i (take new-list (min (length new-list)
             ; if no duplicates allowed then only add item to stack if not
already in the stack
             (when (or allow-duplicate-items?
                       (not (memf (lambda (arg) (string=? arg i))
my-list))) ; not already in the list
               (set! my-list (cons i (take my-list (min (length my-list)

         (define/public (get-list)

(define f
  (new frame%
    [label "Test combo-field%"]
    [min-width 400]
    [min-height 300]

(define combo-field
  (new (class combo-field%

         (inherit get-menu append)

         (define/public (update-choices choice-list)
           ; remove all the old items
             (lambda (i)
               (send i delete))
             (send (get-menu) get-items))
           ; set up the menu with all new items
             (lambda (choice-label)
               (append choice-label))
    [parent f]
    [label "combo-field%"]
    [choices (send small-stack get-list)]
    [stretchable-width #t]
    [stretchable-height #f]

(define add-button
  (new button%
    [label "add"]
    [parent f]
    [callback (lambda (r e)
                (send small-stack add-item (send combo-field get-value))
                (send combo-field update-choices (send small-stack

(define clear-button
  (new button%
    [label "clear"]
    [parent f]
    [callback (lambda (r e)
                (send small-stack clear)
                (send combo-field update-choices (send small-stack

(send f show #t)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20121003/a40a57a6/attachment.html>

Posted on the users mailing list.