[previous] [up] [next]     [index]
Next: Core Windowing Classes Up: Windowing Toolbox Previous: Windowing Toolbox

Windowing Toolbox Overview

MrEd's windowing toolbox provides the basic building blocks of GUI programs, including frames (top-level windows), modal dialogs, menus, buttons, check boxes, text fields, and radio buttons. The toolbox provides these building blocks via built-in classes, such as the frame% class:[footnote]

  ; Make a frame by instantiating the frame% class
  (define frame (make-object frame% "Example"))

; Show the frame by calling its show method (send frame show #t)

The built-in classes provide various mechanisms for handling GUI events. For example, when instantiating the button% class, the programmer supplies an event callback procedure to be invoked when the user clicks the button. The following example program creates a frame with a text message and a button; when the user clicks the button, the message changes:

  ; Make a frame by instantiating the frame% class
  (define frame (make-object frame% "Example"))

; Make a static text message in the frame (define msg (make-object message% "No events so far..." frame))

; Make a button in the frame (make-object button% "Click Me" frame ; Callback procedure for a button click (lambda (button event) (send msg set-label "Button click")))

; Show the frame by calling its show method (send frame show #t)

Programmers never implement the GUI event loop directly. Instead, the system automatically pulls each event from an internal queue and dispatches the event to an appropriate window. The dispatch invokes the window's callback procedure or calls one of the window's methods. In the above program, the system automatically invokes the button's callback procedure whenever the user clicks Click Me.

If a window receives multiple kinds of events, the events are dispatched to methods of the window's class instead of to a callback procedure. For example, a drawing canvas receives update events, mouse events, keyboard events, and sizing events; to handle them, a programmer must derive a new class from the built-in canvas% class and override the event-handling methods. The following expression extends the frame created above with a canvas that handles mouse and keyboard events:

  ; Derive a new canvas (a generic drawing window) class to handle events 
  (define my-canvas% 
    (class canvas% ; The base class is canvas%
           (frame) ; one extra argument, frame, is provided to make-object 
      (override
        ; Method to handle mouse events
        [on-event (lambda (event) (send msg set-label "Canvas mouse"))]
        ; Method to handle keyboard events
        [on-char (lambda (event) (send msg set-label "Canvas keyboard"))])
      ; Call the superclass initialization, providing frame
      (sequence (super-init frame))))

; Make a canvas that handles events in the frame (make-object my-canvas% frame)

(It may be neceesary to enlarge the frame to see the new canvas.) Moving the cursor over the canvas calls the canvas's on-event method with an object representing a motion event. Clicking on the canvas calls on-event. While the canvas has the keyboard focus, typing on the keyboard invokes the canvas's on-char method.

The system dispatches GUI events sequentially; that is, after invoking an event-handling callback or method, the system waits until the handler returns before dispatching the next event. To illustrate the sequential nature of events, we extend the frame again, adding a Pause button:

  (make-object button% "Pause" frame (lambda (button event) (sleep 5))) 
After the user clicks Pause, the entire frame becomes unresponsive for five seconds; the system cannot dispatch more events until the call to sleep returns. For more information about event dispatching, see Eventspaces.

In addition to dispatching events, the GUI classes also handle the graphical layout of windows. Our example frame demonstrates a simple layout; the frame's elements are lined up top-to-bottom. In general, a programmer specifies the layout of a window by assigning each GUI element to a parent container. A vertical container, such as a frame, arranges its children in a column, and a horizontal container arranges its children in a row. A container can be a child of another container; for example, to place two buttons side-by-side in our frame, we create a horizontal panel for the new buttons:

  (define panel (make-object horizontal-panel% frame))
  (make-object button% "Left" panel 
      (lambda (button event) (send msg set-label "Left button click")))
  (make-object button% "Right" panel 
      (lambda (button event) (send msg set-label "Right button click"))) 
For more information about window layout and containers, see Geometry Management.




[previous] [up] [next]     [index]
Next: Core Windowing Classes Up: Windowing Toolbox Previous: Windowing Toolbox

PLT