Open Source im professionellen Einsatz
Linux-Magazin 03/2001
790

Umfangreicheres GUI-Beispiel

Alle bisherigen Beispiele waren so strukturiert, dass ein bestimmtes Sprachmerkmal Schemes gezeigt wurde. In diesem Beispiel werden verschiedene Elemente kombiniert. Da es sich um fast drei Seiten Quelltext handelt (siehe [3]), kann nur auf einige Programmauszüge eingegangen werden.

Listing 7: Erstellen und Anzeigen des Dialogs

(define (make-dialog)
  (let* ((frame (make-object frame% 
                  dialog-title 
                  #f 
                  initial-frame-width
                  initial-frame-height))
         (hp (make-object horizontal-pane% frame))) ;; md 1 
    (set! vp1 (make-vertical-pane hp first-vertical-pane-template))
          ; md 2
    (set! vp2 (make-vertical-pane hp second-vertical-pane-template))
          ; md 2
    (let ((btn-pane (make-button-pane hp)))
          ; md 2
      ;(send frame stretchable-width #f)
      (send frame stretchable-height #f)
      frame)))

So sieht der Dialog aus Listing 7 aus: Ausgabemaske der Adressdaten.

Listing 8: Die Ausgabemaske

(define (make-vertical-pane parent elements)
  ;; a vertical pane just for displayint the contents of a list of
  ;; addresses
  (let ((vertical-pane (make-object vertical-pane% parent))) ; mvp 1
    (let loop ((el elements))
      (cond
        ((null? el) `())
        (else (cons (make-single-text-field
                     (first el) ; label for the field
                     vertical-pane 
                     void ; callback here do nothing
                     initial-text-field-width 
                     initial-text-field-height) ;initial size
                    (loop (cdr el))))))
    vertical-pane))

Der Dialog in Listing 7 besteht aus verschiedenen Elementen (Listing 8). Für den Top-Level bietet sich entweder ein Rahmen (frame) oder ein Dialog (dialog) an (im Beispiel ein Rahmen). In den Rahmen werden ein horizontal ausgerichtetes Element (Kommentar ; md 1) sowie drei Elemente mit vertikal ausgerichteten Unterelementen (; md 2) aufgenommen. Sie vermissen vielleicht Platzierungsanweisungen, doch die benötigt man glücklicherweise nicht, da ein Geometrie-Manager die Elemente verwaltet. Man muss also nicht die einzelnen Elemente so lange verschieben, bis sie endlich passen, sondern legt nur noch fest, welche Elemente in welcher Reihenfolge im Dialog vorkommen sollen.

Bleibt die Frage zu klären, wie die Ausgabemaske aussehen soll. Schauen Sie sich noch einmal die Deklaration der Klasse p2% an. Sie besitzt vier Instanzvariablen für Informationen. Die Ausgabe der Adressen erfolgt in zwei Spalten mit jeweils zwei Textfeldern. Für die Aufnahme der Ausgabefelder wird ein Rahmen mit vertikal ausgerichteten Elementen vorgesehen. Die Funktion make-vertical-pane, abstrahiert das Anlegen einer solchen Spalte.

Beim ersten Parameter handelt es sich um das Element, in das eine neue Spalte eingefügt werden soll. (Kommentar ; mvp1). Der zweite Parameter ist eine Liste aus Zeichenketten, mit denen das Textfeld beschriftet wird. Für die Bedienung ist eine Knopfleiste vorgesehen (Listing 9).

Listing 9: Erstellung einer Knopfleiste zur Interaktion

<b-5>si(define (make-button-pane parent)
  ;; two buttons to click through a list of addresses
  ;; one quit button for finishing the program
  (let ((button-pane (make-object vertical-pane% parent)))
    (let loop ((btn-list (button-list-template)))
      (cond 
        ((null? btn-list) `())
        (else (cons (send (make-button 
                           (list-ref (first btn-list) 
                                     button-label-const)
                           button-pane
                           (list-ref (first btn-list)
                                     button-callback-const)) 
                          min-width initial-button-width) ; bp 1
                    (loop (rest btn-list))))))
    button-pane))

Auch hier wurde das gleiche Schema wie für die Textfelder angewandt. Allerdings sieht die zu verarbeitende Liste etwas anders aus:

(define (button-list-template) 
  `(("&previous" ,previous-button-callback)
    ("&next" ,next-button-callback)
    ("&Quit" ,quit-button-callback)))

Die Liste besteht aus einem Namen und einem ausgewerteten Symbol. Betrachten wir beispielhaft das erste Element der Liste. Der Knopf wird mit previous beschriftet. Die zugehörige Callback-Funktion hat den Namen previous-button-callback. Das Symbol wird ausgewertet und man erhält die dahinter stehende Funktion, die als Callback-Funktion registriert werden kann.

Der Vorteil der indirekten Vorgehensweise liegt in der möglichen Wiederverwendbarkeit von Methoden, die -- in diesem Fall -- Ausgabespalten generieren. Außerdem lassen sich so die Anwendungsdaten des Programms an einem Punkt bündeln. Etwaige Änderungen wie zum Beispiel das Hinzufügen eines weiteren Feldes, sind einfach vorzunehmen.

Da die Knöpfe die gleiche Ausdehnung haben sollten, wurde eine Mindestbreite (; bp 1) vorgesehen. Das Zeichen & vor einzelnen Buchstaben kennen Sie vielleicht von Windows. Damit legen Sie fest, mit welcher Tastaturkombination der Knopf zusätzlich bedient werden kann.

Betrachten wir nun die Implementierung für einen Knopf aus der Knopfleiste. Sie sehen in Listing 10, dass counter immer um eins erniedrigt wird, es sei denn, man befindet sich am Ende der Liste, dann wird counter auf die Anzahl der Elemente der Liste gesetzt. Sie können sich also beliebig lange durch diese Liste bewegen. In der Funktion update-persons-data werden die Daten der aktuellen Person angepasst und die neuen Werte in die Ausgabeelemente eingetragen.

Listing 10: Callback für den Knopf Previous

(define (previous-button-callback button event)
  (if (= counter 0)
      (set! counter number-of-persons)
      (set! counter (- counter 1)))
  (update-persons-data))

Zusammenfassung

In diesem Teil haben Sie gesehen, dass Scheme nicht nur für die funktionale Programmierung eingesetzt werden kann, sondern dass die Sprache offen für Erweiterungen und andere Vorgehensweisen ist, etwa die objektorientierte Programmierung. DrScheme und eine Reihe weiterer Scheme-Implementierungen (www. schemers.org) bieten Objektsysteme zur objektorientierten Programmierung an. Das von DrScheme ist nicht das umfangreichste, es ist aber einfach zu verstehen und reicht zur Implementierung eines nicht trivialen Systems (MrEd) aus.

Die Art und Weise der Bedienung des Systems weist auf eine ähnliche Implementierung wie in [1] hin. Offensichtlich reichen lexikalische Bindung und Funktionen aus, ein Objektsystem zu implementieren -- was ich bemerkenswert finde.

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Standards? Standards!

    Der Scheme-Standard hat einen recht kleinen Umfang, also greifen Programmierer für größere Projekte zwangsläufig auf Erweiterungen zurück. Im Zentrum dieses Artikels stehen daher Standard-Scheme und seine Erweiterungen.

  • Funktioneller gehts nicht

    Nachdem im vorherigen Teil die Basiselemente der Scheme-Programmierung vorgestellt wurden, soll in diesem Artikel ein essentieller Vorteil von Scheme die Hauptrolle spielen, nämlich die funktionale Programmierung.

  • Wechsel auf der Brücke

    Scripting funktioniert nicht nur bei den üblichen Verdächtigen wie Bash, Korn-Shell und Python, sondern auch mit Scheme. Im Zentrum des Artikels stehen darum die Shell-Programmierung mit Scheme sowie die Programmierung fürs Internet.

  • PLT-Scheme 4.0 mit vielen Neuerungen

    PLT-Scheme, ein Softwarepaket bestehend aus Scheme-Implementierung und Entwicklungsumgebung, ist in Version 4.0 erschienen. Die Entwickler haben rund ein Jahr in die neue Release investiert.

  • Web-Wunder

    Mit Scheme setzt das freie Web-Framework Hop eine ziemlich esoterische Programmiersprache ein. Seine Architektur und Flexibilität machen es jedoch zu einer spannenden Alternative zu Django & Co.

comments powered by Disqus

Stellenmarkt

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.