You would like to deal with many widgets as though they were a single widget.
(require (lib "mred.ss" "mred")
(lib "framework.ss" "framework")
(lib "class.ss"))
(define my-widget%
(class* panel:single% ()
(init-field parent)
(define a-button
(new button%
(label "Press Me")
(parent parent)
(callback void)))
(define a-text-field
(new text-field%
(label "Enter Text")
(parent parent)
(callback void)))
(super-instantiate () (parent parent))
))
(define top-frame (instantiate frame% () (label "Example")))
(define new-my-widget (new my-widget% (parent top-frame)))
(send top-frame show #t)
GUI programming is non-standard. A PLT Solution has been given.
When designing a GUI, it is common to design widget groups that are reused. This is done by creating a subclass of the panel type and defining the widgets in that class.
The above sample displays a push button with the label "Push Me" above a Text Box with the label "Enter Text". Both widgets will be center justified and the enclosing window is as small as it can be while still showing the widgets in full.
The first thing to do when using
MrEd and the PLT class library is to import the modules:
(require (lib "mred.ss" "mred"))
(require (lib "framework.ss" "framework"))
(require (lib "class.ss"))
Then, we would like to define a class and bind it to a name. It is customary in
MrEd to suffix widgets with a
% and interfaces with a
<%>. This will be a subclass of the panel:single% widget which will provide layout geometry for child widgets. It will not implement any interface so we will give it an empty list for the
interface-expression.
(define my-widget%
(class* panel:single% ()
))
Since panel widgets cannot be top level windows (
frames in the
MrEd and wxWidget nomenclature), we must give this widget a parent that must be set on instantiation. This is done with the init-field expression:
If we wanted, we could set it to an initial value much the same way we set initial values in a
let expression.
The next step is to define the widgets. This is quite straight forward:
(define a-button
(new button%
(label "Press Me")
(parent parent)
(callback void)))
(define a-text-field
(new text-field%
(label "Enter Text")
(parent parent)
(callback void)))
The final part is to initialize the superclass. As we mentioned before, panels cannot be top level windows, so they must have parents. That means we need to pass the parent parameter to the super-instantiate expression:
(super-instantiate () (parent parent))
Don't worry that the parent expression has the same name as the parameter. The values are resolved by position in the expression as well as name, so Scheme won't be confused.
Constructing and showing the window are straight forward:
(define top-frame (instantiate frame% () (label "Example")))
(define new-my-widget (new my-widget% (parent top-frame)))
(send top-frame show #t)
If you meant for the widget to be a panel grouping the button and the text field, then the code for the above class should be:
(define my-widget%
(class panel:single%
(init-field parent)
(super-new [parent parent])
(let ([p (new vertical-panel% [parent this])])
(new button%
[label "Press Me"]
[parent p] [callback void])
(new text-field%
[label "Enter Text"]
[parent p] [callback void]))))
--
DanielSilva - 03 Jul 2005
Whats the difference?
--
StephenDeGabrielle - 21 Sep 2007
Here is another example - but but the widget is created from drawing toolkit elements, rather than existing widgets.
(define scatter-chart% (class pane% ()
(init-field parent)
(super-instantiate () (parent parent) [min-width 100] [stretchable-width #f]
(min-height 200) [stretchable-height #f])
(define list-of-points '()) (define canvas (new canvas% [parent this]
(paint-callback (lambda (canvas dc) (draw-chart)))
[min-width 100] [stretchable-width #f]
[min-height 200] [stretchable-height #f]
))
(define dc (send canvas get-dc)) (define no-pen (make-object pen% "BLACK" 1 'transparent))
(define blue-brush (make-object brush% "BLUE" 'solid))
(define yellow-brush (make-object brush% "YELLOW" 'solid))
(define/public (add-point new-point)
(set! list-of-points (cons new-point list-of-points)) (send dc draw-rectangle 0 new-point 200 1)) (define/public (draw-chart)
(send dc set-pen no-pen)
(send dc set-brush blue-brush)
(send dc draw-rectangle 0 0 100 200) (send dc set-brush yellow-brush)
(map
(lambda (y) (send dc draw-rectangle 0 y 200 1)) list-of-points ))
(draw-chart)))
(define frame (new frame% [label "scatter-chart% Example"] [width 100] [height 200]))
(send frame show #t)
(define new-my-widget (new scatter-chart% (parent frame) )) (define new-his-widget (new scatter-chart% (parent frame) ))
(send new-my-widget draw-chart)
(define (go)
(map (lambda (y)
(send new-my-widget add-point y) (sleep/yield 0.05)) '(10 30 22 77 78 79 17 65 97 54 55 56 57 91 33 55 95 99 125 155 157 159 188 187 186 191)))
(go)
--
StephenDeGabrielle - 21 Sep 2007
--
EwanHiggs - 01 Sep 2004