Die Kommandozeile macht sich schön

Einführung in Tcl/Tk, Teil 3

Tcl/Tk, kurz gefasst

Die Programmiersprache Tcl/Tk besteht aus der leicht erlernbaren Programmiersprache Tcl und der Widget-Library Tk. Tcl/Tk (ausgesprochen: "Tickel-Tikej") erlaubt unter anderem die höchst einfache und effiziente Programmierung von grafischen Benutzeroberflächen. Der Programmcode wird von einem Interpreter ausgeführt, der für Linux, verschiedene andere Unixbetriebssysteme, Windows, MacOS und OS/2 verfügbar und freie Software ist.

Wir leben in einer schönen Zeit: Alles soll bunt und lustig sein, und da mutet es fast altmodisch an, ein Kommandozeilenprogramm zu verwenden. Außerdem ist alles schnelllebig, so will sich natürlich niemand eine Kommandozeile mit mehr als einer Option merken. Um trotzdem diese wundervollen Programme nutzen zu können, ist es höchst praktisch, sich und vielleicht auch anderen bei Bedarf eine grafische Oberfläche zu erstellen, die das Kommandozeilenprogramm fernsteuert, indem nur auf Knöpfchen gedrückt wird.

Nachdem Sie im letzten Artikel dieser Serie [8,9] ein interaktives Kommandozeilenprogramm für den Raytracer Povray geschrieben haben, soll diesmal eine grafische Oberfläche entstehen, deren Funktionalität Sie im vierten und letzten Teil ergänzen.

Ein paar Worte zu Povray

Povray kann photorealistische Bilder erzeugen, indem es eine Datei einliest, in der Sie eine Szene ähnlich wie mit einer Programmiersprache beschrieben haben. Falls Sie noch nie mit Povray in Berührung gekommen sind, machen Sie sich bei Bedarf z.B. mit Hilfe des Artikels von Christian Perle [1] schlau.

Doch auch, wenn Sie sich nicht für Povray interessieren, können Sie die vorliegende Einführung in Tcl/Tk sinnvoll nutzen: Das Programm dient nur als Beispiel, um das Vorgehen beim Erstellen einer Oberfläche zu erklären.

Wenn Povray Ihnen eine Szene mit einer bestimmten Größe rendern und eine Bilddatei erstellen soll, lautet die Kommandozeile:

povray +Iname_der_szenendatei +Oname_der_bilddatei +Wbildbreite +Hbildhöhe

Im Folgenden geht es darum, diese Zeile durch ein wunderschönes grafisches Programm erzeugen zu lassen.

Der die Arbeit tut

Um ein Tcl/Tk-Programm zu schreiben, müssen Sie in Ihrer Programmdatei zunächst den Tcl/Tk-Interpreter – wish – aufrufen. Nachdem Sie im ersten Teil dieser Reihe den Interpreter im Terminal gestartet und ihm Ihre Datei als Argument mit gegeben haben, wurde er im zweiten Teil von Ihrem Programm selbst aufgerufen. Allerdings musste dazu der komplette Pfad des Interpreters in Ihrem Programm stehen. Wollten Sie Ihr Tcl/Tk-Skript nun auf einem anderen Rechner ausführen, auf dem zwar die wish installiert ist, sich aber an einer anderen Stelle befindet, dann funktionierte Ihr Programm nicht, und Sie mussten es ändern.

Um das zu vermeiden (also ein portables Programm zu schreiben), gibt es einen Trick: Sie starten zunächst die Standardshell des Systems, was auf jedem Unixsystem durch die Zeile #!/bin/sh gelingt, lassen diese nach der wish suchen und selbige starten. Dazu schreiben Sie folgende Zeilen mit Ihrem Lieblingseditor:

#!/bin/sh
#\
exec wish "$0"

In der ersten Zeile wird die Standardshell gestartet und arbeitet Ihr Programm ab. Sie übersieht die zweite Zeile, da an deren Anfang ein Kommentarzeichen (#) steht. In der dritten Zeile ersetzt sich /bin/sh dann selbst durch den Tcl/Tk-Interpreter wish und übergibt ihm mit "$0" den Namen Ihres Programms zur Ausführung.

Die wish liest Ihre Datei ein, ignoriert aber diese ersten drei Zeilen. Bei den ersten beiden ist das klar, da sie mit einem Gatter # beginnen. Am Ende der zweiten Zeile steht nun aber ein Backslash (\). Dieser macht aus der dritten Zeile die Fortsetzung der zweiten – also auch einen Kommentar. Damit diese Zeilenfortsetzung funktioniert, darf übrigens kein Zeichen – auch kein Leerzeichen – mehr hinter dem Backslash stehen!

Wenn Sie diesen Dreizeiler geschrieben haben, können Sie Ihre Programmdatei vorsorglich schon mal speichern, wobei sich der Name povgui.tcl anbietet. Machen Sie die Datei danach in einem Terminal durch die Eingabe von chmod +x povgui.tcl ausführbar.

Wenn Sie sie jetzt durch die Eingabe von /povgui.tcl in einem Terminal ausführen, passiert aber nichts weiter, als dass ein Fenster aufploppt, auf dem der Name Ihres Programms, also povgui.tcl, steht. Sie können es getrost durch den gleichzeitigen Druck auf die Steuerungstaste Strg und die Taste c wieder beenden und mit dieser Einführung weiter machen.

Immer, wenn Sie prüfen wollen, ob das, was Sie im Folgenden programmieren werden, auch geklappt hat, speichern Sie Ihre Programmdatei und rufen sie mit povgui.tcl auf. Dabei kann es vor allem am Anfang passieren, dass Sie sich z.B. vertippt haben und Fehlermeldungen statt Buttons zu sehen bekommen. Lassen Sie sich davon aber nicht entmutigen. Der Interpreter führt nur aus, was Sie tatsächlich geschrieben – und nicht, was Sie "gemeint" haben.

Optik

Bei der Entwicklung Ihres grafischen Programms verfahren Sie in vier Schritten:

  • Sie überlegen sich die Funktionen, die das Programm zur Verfügung stellen soll.
  • Sie finden heraus, wie die Nutzer auf Funktionen zugreifen sollen und erstellen einen ersten Prototypen auf Papier.
  • Sie programmieren die grafische Darstellung ohne Funktionen.
  • Wenn Ihnen alles gefällt, programmieren Sie die Funktionen hinzu.Überlegen Sie also als Erstes, was Ihre Oberfläche können soll bzw. was die spätere Nutzerin des Programms an Funktionalität braucht. Lehnen Sie sich zurück, und stellen Sie sich vor, wie Sie oder diejenige, die Sie mit Ihrem GUI beglücken möchten, vor dem Rechner sitzt und Povray bedienen will.

Das könnte z.B. so aussehen: Sie ist gerade dabei, mit einem Editor ihrer Wahl die Datei mit der Povray-Szenenbeschreibung zu erstellen, und möchte nun einfach einen Button drücken, um ihre neuesten Änderungen bildlich zu sehen. Dazu muss die Szene zunächst gerendert und die Bilddatei dann von einem Grafikprogramm angezeigt werden.

Ihre Nutzerin möchte die Größe des zu rendernden Bilds variieren können, um während des Entwicklungsprozesses kleine und am Ende größere Bilder zu berechnen. (Je größer das Bild, desto länger dauert der Povray-Lauf, und so lange möchte sie bei der Entwicklung dann auch nicht immer warten.) Außerdem will sie den Bildern unterschiedliche Namen geben, um auch Zwischenschritte zu dokumentieren.

Damit ist die Funktionalität Ihres Programms klar und im Kasten "Die Funktionen von povgui" zusammen gestellt.

Die Funktionen von Povgui

  • Eine Möglichkeit zum Auswählen der Datei mit der Szenenbeschreibung.
  • Eine Möglichkeit zum Auswählen der Bilddatei, wobei es nett wäre, wenn das Programm aus dem Namen der Szenendatei einen Vorschlag generiert (Austausch der Dateiendung von .pov nach .tga, siehe auch [8,9]).
  • Einstellmöglichkeiten für Bildhöhe und Bildbreite.
  • Ein Knopf zum Rendern der Szenendatei.
  • Ein Button zum Anzeigen des gerenderten Bilds.

Nun kommt Teil Zwei der Programmentwicklung: Sie müssen sich überlegen, wie Sie diese Funktionen so zur Verfügung stellen, dass sie von der Nutzerin möglich einfach zu bedienen sind, wobei Sie sich so weit möglich an bestehenden Anwendungen orientieren sollten. Zeichnen Sie dann eine kleine Skizze, in der Sie die grobe Form des GUI festlegen. Ja, am besten geht das mit Papier und Bleistift, zum Beispiel so wie in Abbildung 1.

Abbildung 1

Abbildung 1: Erster Prototyp auf Papier

Oberflächlichkeiten

Anschließend gehen Sie daran, diese Oberfläche zu programmieren. Dazu greifen Sie in die Widget-Trickkiste von Tk. In Abbildung 2 sehen Sie das GUI mit der Beschreibung der einzelnen Fensterelemente.

Abbildung 2

Abbildung 2: Die verwendeten Fensterelemente

Bevor Sie loslegen, noch ein paar Worte zu den Widgets und ihrer Organisation.

In Tk sind die Definition und die Anzeige von Fensterelementen voneinander getrennt. Zunächst legen Sie ein Widget fest und bestimmen dessen Konfiguration wie z.B. seine Aufschrift, Farbe etc. Danach erst übergeben Sie es einem Geometrie-Manager, der es anzeigen lässt.

Wählen können Sie aus drei Geometrie-Managern, die die Darstellung der Widgets unterschiedlich handhaben. Heute lernen Sie zwei davon kennen: pack und grid.

Geometrie-Manager haben die Aufgabe, den ihnen übergebenen Widgets genug Raum zur Verfügung zu stellen. Sie organisieren die Fensterelemente hierarchisch, wobei jedes Widget das Kind eines Eltern-Widgets ist. Die Urahnin aller Widgets ist das Fenster, das Ihr Programm umhüllt. Es trägt den Namen "Punkt" (.). Dieses "Ur-Widget" dient als Container für die Widgets, die darin angezeigt werden sollen. Es gibt aber auch noch andere Fensterelemente, die die Aufgabe von Containern übernehmen, zum Beispiel Frames (Rahmen).

Die Geometrie-Manager grid und pack weisen den ihnen übergebenen Widgets eine "Höhle" innerhalb ihrer Eltern-Widgets zu, die mindestens so groß ist, dass das jeweilige Kind-Widget genug Platz hat. Dieser Raum kann aber auch größer als das Widget sein, wenn sein Nachbar einen größeren Platzbedarf hat.

Der "packer" ordnet die Widgets neben- oder übereinander an, je nachdem, mit welchen Optionen er sie übergeben bekommt. Während dessen organisiert der "gridder" seine Widgets in Zeilen und Spalten wie eine Tabellenkalkulation.

Die Höhlen des packers sind in Abbildung 3, die des gridders in Abbildung 4 dargestellt.

Abbildung 3

Abbildung 3: Der packer …

Abbildung 4

Abbildung 4: … und der gridder in Aktion

Beide Geometrie-Manager haben ihre Vorteile, und Sie dürfen sich jeweils den passenden für Ihre Problemlösung aussuchen. Zunächst müssen Sie dazu analysieren, wie Ihre Widgets aufgebaut sind.

Strukturelles

Wenn Sie den Prototypen anschauen, können Sie ihn nach der Organisation der Widgets in drei Bereiche unterteilen:

  • Oben die Menüleiste: Nur ein Widget auf einer Seite.
  • In der Mitte das Eingabefeld und die Skalen, jeweils mit der Beschriftung links daneben: Die Widgets sind in Zeilen und Spalten angeordnet.
  • Unten die beiden Knöpfe zum Rendern und Anzeigen: Die Widgets liegen nebeneinander.Wenn Sie diese drei Teile durch drei Frames herstellen, können Sie innerhalb der Rahmen die darin liegenden Widgets vom passenden Geometrie-Manager verstauen lassen. Für die nebeneinander stehenden Widgets ist der packer optimal, während sich für die Zeilen- und Spaltenstruktur in der Mitte der gridder besser eignet.

Rahmenhandlung

Nun kommt Teil Drei der GUI-Entwicklung: Das Programmieren der Oberfläche ohne Funktionen. Zuerst geht es darum, die Struktur des GUI mit Frames fest zu legen.

Frames sind die einfachsten Widgets: In der Grundform sind sie viereckig und unsichtbar und dienen dazu, andere Widgets als Kinder aufzunehmen und anzuordnen. Werden Frames mit zusätzlichen Optionen definiert, können sie allerdings doch noch ein dreidimensionales Aussehen annehmen und Gruppen von Widgets auch optisch voneinander absetzen.

Der Aufruf, der einen Rahmen erzeugt, ist denkbar einfach: Er besteht nur aus dem Befehl selbst und dem Namen des Frames, der wie alle Widgetnamen mit einem Punkt beginnen muss. Damit die Frames ein dreidimensionales Aussehen bekommen, können Sie die Option -relief Reliefart verwenden, wobei das Relief flat (flach), raised (erhaben), groove (mit einem kleinen eingesunkenen Rand) oder ridge (mit kleinem erhabenen Rand) sein kann. Um dieses Relief sichtbar zu machen, brauchen die Frames aber auch noch eine Kantenbreite, die Sie durch die Option -borderwidth Breite (Breite in Pixeln) festlegen.

frame .obererRahmen    -borderwidth 1 -relief raised
frame .mittlererRahmen -borderwidth 1 -relief raised
frame .untererRahmen   -borderwidth 1 -relief raised

Mit dem Hinzufügen dieser Zeilen zu Ihrer Programmdatei sind die Frames angelegt – sie müssen lediglich noch angezeigt werden. Da sie einfach untereinander angeordnet sind, bietet sich dafür der packer an. Übergeben Sie diesem Geometrie-Manager die drei Rahmen, und sagen Sie ihm mit der Option -side Richtung die Richtung, aus der er sie einfüllen soll.

Um Widgets nebeneinander anzuordnen, verwenden Sie left oder right, bei übereinander stehenden Widgets wird top oder bottom für Richtung eingesetzt.

Der packer macht aber jedes Widget nur so groß, wie es unbedingt sein muss. Ist das benachbarte Widget breiter, so bleibt Platz übrig, was Sie gut in Abbildung 3 sehen können. Wollen Sie hingegen, dass Ihre Widgets die zur Verfügung stehende Höhle gänzlichst ausfüllen, ergänzen Sie die Option -fill Richtung. Für Richtung kann x, y oder both angegeben werden.

pack .obererRahmen    -side top -fill x
pack .mittlererRahmen -side top -fill x
pack .untererRahmen   -side top -fill x

Sollten Sie jetzt ausprobieren, wie Ihr Programm aussieht, werden Sie wie in Abbildung 5 – fast – nichts sehen. Ihr Fenster ist nur so groß wie nötig und – da Frames selbst keinen Platz brauchen – beinahe verschwunden. Das wird sich ändern, wenn Sie nun andere Widgets hinein programmieren.

Abbildung 5

Abbildung 5: Unsichtbare Frames

Am einfachsten sind die Buttons, daher soll damit begonnen werden.

Auf Knopfdruck

Der Befehl, um einen Button zu erzeugen, besteht aus dem Kommando button und dem Namen des Knopfs. Ohne Aufschrift sind Buttons aber einigermaßen sinnlos, daher sollten Sie auch noch die Option -text Aufschrift verwenden. Ein Kommando bekommen die Buttons jetzt noch nicht mit auf den Weg. Das erhalten sie erst im vierten GUI-Entwicklungsschritt, wenn das GUI genauso aussieht wie es soll.

button .renderKnopf  -text Rendern
button .anzeigeKnopf -text Anzeigen

Dann übergeben Sie die Buttons dem packer. Sie sollen Kinder des unteren Frames werden, daher ist die Option -in Eltern-Widget nötig. Um die Buttons in einer Reihe anzuordnen, geben Sie die Option -side left mit. Damit die Knöpfe die ganze Framebreite füllen, reicht diesmal die Option -fill x nicht aus. Sie müssen zusätzlich noch -expand yes mitgeben, um die Buttons mitwachsen zu lassen, wenn die anderen, später gefüllten Frames breiter werden.

pack .renderKnopf  -in .untererRahmen \
    -side left -fill x -expand yes
pack .anzeigeKnopf -in .untererRahmen \
    -side left -fill x -expand yes

Alles Gute kommt von oben

Widmen wir uns jetzt der Menüzeile. In ihr liegt links ein Menübutton, von dem aus ein Pull-Down-Menü herunter geklappt wird, wenn die Nutzerin mit der Maus darauf klickt.

Definieren Sie zunächst den Menübutton wie einen "ganz normalen" Button mit Aufschrift, ergänzen dann aber eine weitere Option -menu Pull-down-Menue-Name. Das Pull-Down-Menü ist ein Kind des Menübuttons, sein Name muss von diesem abgeleitet sein, also aus zwei Teilen bestehen: dem Namen des Buttons und dem des Menüs.

Danach erzeugen Sie das Menü durch den Befehl menu Pull-down-Menue-Name. Am Ende ergänzen Sie es mit Pull-down-Menue-Name add Eintrag um die einzelnen Einträge, die Befehle (command) oder Trennstriche (separator) sein können.

Bei Menü-Einträgen wird die Aufschrift, abweichend von der Definition bei Buttons, mit der Option -label Aufschrift fest gelegt.

Obwohl eigentlich erst in Teil 4 an der Reihe – Ausnahmen bestätigen Regeln –, fügen Sie schon einmal eine Funktion hinzu: das Kommando zum Beenden Ihres Programms mit -command Kommando.

menubutton .dateiKnopf -text Datei \
    -menu .dateiKnopf.herunterklappMenue
menu .dateiKnopf.herunterklappMenue
.dateiKnopf.herunterklappMenue add command \
    -label "Szenendatei wählen ..."
.dateiKnopf.herunterklappMenue add separator
.dateiKnopf.herunterklappMenue add command \
    -label "Beenden" -command exit

Die Anzeige des Pull-Down-Menüs wird vom Menübutton übernommen und muss nicht extra veranlasst werden. Ihren Menübutton hingegen müssen Sie noch einem Geometrie-Manager übergeben. Auch hier bietet sich der packer an.

pack .dateiKnopf -in .obererRahmen -side left

Die goldene Mitte

Im Mittelteil stehen jeweils links Beschriftungen ("Label") mit der Erläuterung, was im rechts daneben liegenden Widget eingestellt wird. Labels sind Einfach-Widgets, die von sich aus kein 3D-Aussehen haben, sondern einfach nur Text anzeigen.

Sie benötigen drei Labels: für den Bildnamen, die Bildbreite und die -höhe.

label .bildnameAufschrift   -text Bildname
label .bildbreiteAufschrift -text Bildbreite
label .bildhoeheAufschrift  -text Bildhöhe

Bleibt der rechte Teil der Mitte: In der obersten Reihe liegt das Eingabefeld. Später wird darin der Name der Bilddatei angezeigt und kann von der Nutzerin geändert werden. Im Moment interessiert aber nur die reine Optik. Legen Sie das Feld also einfach mit dem Befehl entry, gefolgt von seinem Widgetnamen, an. Um auch genug Platz für längere Dateinamen zu haben, können Sie jetzt schon einmal festlegen, dass im Entry 30 Buchstaben gleichzeitig sichtbar sein sollen. Dies erreichen Sie durch die Option -width Zahl, wobei Zahl die sichtbaren Buchstaben angibt:

entry .bildnameEingabefeld -width 30

Unter dem Eingabefeld liegen die Schieberegler ("Scale"). Diese kennen außer den "normalen" Optionen noch jeweils eine für den Startwert der Skala (-from Zahl) und ihren Endwert (-to Zahl).

Normalerweise werden Skalen senkrecht stehend dargestellt. Im Prototypen sind sie aber waagerecht eingezeichnet. Deswegen brauchen Sie zusätzlich noch die Option -orient horizontal:

scale .bildbreiteScale -from 20 -to 400 -orient horizontal
scale .bildhoeheScale  -from 20 -to 400 -orient horizontal

Nun sollen die Widgets angezeigt werden. Damit betrauen wir diesmal den gridder. Ihm muss auch wieder der Widgetname und nach der Option -in Eltern-Widget das Eltern-Widget mitgeteilt werden. Danach folgen allerdings andere Optionen.

Jedes Widget kommt in eine Zelle, deren Lage durch die Zeilenangabe -row Nummer und ihre Spaltennummer (-column Nummer) fest gelegt wird, wobei sowohl die Zeilen- als auch die Spaltenzählung bei 0 beginnt. Die Spalten werden von links nach rechts gezühlt, die Reihen von oben nach unten. Innerhalb dieser Zelle können die Widgets an den Zellwänden "fest geklebt" werden. Dies funktioniert mit der Option -sticky Richtung. Als Richtung dienen w,e,n oder s für die Himmelsrichtungen. Werden gegenüber liegende Richtungen angegeben, dehnt sich das Widget so weit, bis es die jeweiligen Zellwände berührt.

grid .bildnameAufschrift   -in .mittlererRahmen -row 0 -column 0 -sticky sw
grid .bildnameEingabefeld  -in .mittlererRahmen -row 0 -column 1 -sticky we
grid .bildbreiteAufschrift -in .mittlererRahmen -row 1 -column 0 -sticky sw
grid .bildbreiteScale      -in .mittlererRahmen -row 1 -column 1 -sticky we
grid .bildhoeheAufschrift  -in .mittlererRahmen -row 2 -column 0 -sticky sw
grid .bildhoeheScale       -in .mittlererRahmen -row 2 -column 1 -sticky we

Dem Ganzen einen Namen geben

Zu guter Letzt bleibt noch die Korrektur eines kleinen Schönheitsfehlers: Vielleicht ist Ihnen aufgefallen, dass in der Titelzeile Ihres Programms immer povgui.tcl steht. Falls Sie dort lieber einen anderen Titel sehen möchten, z.B povgui, dann können Sie den Tk-Window-Manager wm anweisen, ihn für Sie zu ändern. Sie müssen ihm dazu den Namen des betreffenden Fensters mitgeben, hier also den des Ur-Widgets ".":

wm title . povgui

Wenn Sie Ihr Programm nun laufen lassen, es so aussieht wie in Abbildung 2 und Ihnen dazu noch gefällt, dann haben Sie gewonnen. Aber vielleicht möchten Sie ja noch ein wenig daran feilen?

Die hier im Text verwendeten Optionen (und auch noch ein paar andere) sind in Tabelle 1 zusammen gestellt. Sie soll Ihnen dabei helfen, das GUI Ihren Wünschen anzupassen.

Im letzten Teil dieser Serie lernen Sie dann, Prozeduren zu schreiben, Dateimanager aufzurufen und all dieses Wissen in Ihr GUI einzubauen.

Tabelle 1: Optionen für Tk-Widgets

Allgemeine Optionen für alle Widgets
-borderwidth Pixel Kantenbreite. Für "normales" 3D-Aussehen ist die Borderwidth 2 Pixel breit.
-relief Reliefart Aussehen eines Widgets. Abbildung 6 zeigt die möglichen Reliefarten.
Optionen für alle Widgets mit Schrift
-text Aufschrift Aufschrift eines Widgets.
-width Breite Breite des Widgets in Zeichen.
-foreground Farbe Schriftfarbe. Farbe kann durch Standardfarbnamen des Systems (zu finden in der Datei rgb.txt) oder in der #RRGGBB-Schreibweise als Zusammenstellung der Farbanteile von Rot, Grün und Blau angegeben werden. Die Anteile legt man hexadezimal (also mit den Ziffern 0 für Null bis f für 15) fest. Schwarz ist #000000, Weiß #ffffff, Rot #ff0000 usw.
-background Farbe Widget-Hintergrund. Die Farbe wird wie bei -foreground angegeben.
-anchor Richtung Die Richtung, in der die Aufschrift eines Widgets beginnt. Richtung kann n, s, e und w für die Himmelsrichtungen sein.
Optionen für Buttons, Labels und Menübuttons
-image [image create photo -file Bildname ] Zeigt auf einem Button oder Label ein Bild an. Bildname muss ein Bild im Format png, pgm oder ppm sein und kann mit relativem oder absolutem Pfad angegeben werden. image create photo macht die mit Bildname übergebene Bilddatei für Tk lesbar. Wegen der eckigen Klammern wird das Ergebnis dann an die Option -image weitergegeben.
-font { Font } Font ersetzt man durch einen Schriftnamen wie z.B. Helvetica 20 oder die genaue Bezeichnung wie Adobe-Helvetica-Medium-R-Normal--*-180-*.
-command { Befehl } Der bei einem Buttonklick ausgeführte Befehl. Um Unix-Befehle auszuführen, muss ihnen ein exec voraus gehen, z.B. exec netscape. (Gilt nicht für Labels.)
-menu Menüname Bindet ein Menü an den Menübutton. Dieses muss allerdings explizit mit dem Befehl menu Menüname angelegt werden. (Gilt nur für Menübuttons.)
Optionen für Scales
-orient Richtung Bezeichnet die Richtung, in der die Skala verlaufen soll. Richtung kann horizontal oder vertical sein.
-from Zahl Startwert einer Skala. Die Voreinstellung für Zahl ist 0.
-to Zahl Endwert einer Skala. Zahl ist auf 100 voreingestellt.
Abbildung 6

Abbildung 6: Reliefarten

Tabelle 2: Die verwendeten Optionen des Geometrie-Managers pack

-side Richtung Die Seite, von der die Widgets "eingefüllt" werden. Richtung kann left, right, bottom oder top sein. Bei top und bottom liegen die Widgets übereinander, bei left und right nebeneinander.
-expand yes Ermöglicht, dass die Widgets "mitwachsen", wenn die Fenstergröße von der Nutzerin geändert wird.
-fill Richtung Richtung, in der die Widgets ausgedehnt werden sollen. Mögliche Werte: x, y, both.

Tabelle 3: Die vorgestellten Optionen des Geometrie-Managers grid

-row Zeile Zeile, in der das Widget erscheinen soll.
-column Spalte Spalte, in der das Widget angezeigt werden soll.
-sticky Richtung Richtung, in der die Widgets "angeklebt" werden, um sich bis zur Zellenwand auszudehnen. Als Richtungen dienen eine oder mehrere der Himmelsrichtungen w, e ,n, s (ohne Komma oder Zwischenraum bei mehreren Angaben).
-rowspan Anzahl Anzahl der Zeilen, über die sich ein Widget erstreckt, falls es über eine Zeile hinaus gehen soll.
-columnspan Anzahl Anzahl der Spalten, die ein Widget überstreicht, sofern größer als Eins.

Listing 1

povguis Oberfläche

#!/bin/sh
#\
exec wish "$0"
# Die Frames, in denen die anderen Widgets angeordnet werden:
frame .obererRahmen    -borderwidth 1 -relief raised
frame .mittlererRahmen -borderwidth 1 -relief raised
frame .untererRahmen   -borderwidth 1 -relief raised
pack .obererRahmen    -side top -fill x
pack .mittlererRahmen -side top -fill x
pack .untererRahmen   -side top -fill x
# Die Buttons in der unteren Zeile:
button .renderKnopf  -text Rendern
button .anzeigeKnopf -text Anzeigen
pack .renderKnopf  -in .untererRahmen \
    -side left -fill x -expand yes
pack .anzeigeKnopf -in .untererRahmen \
    -side left -fill x -expand yes
# Der Menübutton mit Menü:
menubutton .dateiKnopf -text Datei -menu .dateiKnopf.herunterklappMenue
menu .dateiKnopf.herunterklappMenue
.dateiKnopf.herunterklappMenue add command -label "Szenendatei wählen ..."
.dateiKnopf.herunterklappMenue add separator
.dateiKnopf.herunterklappMenue add command -label "Beenden" -command exit
pack .dateiKnopf -in .obererRahmen -side left
# Die Beschriftung für Eingabefeld und Schieberegler:
label .bildnameAufschrift   -text Bildname
label .bildbreiteAufschrift -text Bildbreite
label .bildhoeheAufschrift  -text Bildhöhe
# Eingabefeld und Schieberegler:
entry .bildnameEingabefeld -width 30
scale .bildbreiteScale -from 20 -to 400 -orient horizontal
scale .bildhoeheScale  -from 20 -to 400 -orient horizontal
# Anordnen der Widgets im mittleren Teil:
grid .bildnameAufschrift   -in .mittlererRahmen -row 0 -column 0 -sticky sw
grid .bildbreiteAufschrift -in .mittlererRahmen -row 1 -column 0 -sticky sw
grid .bildhoeheAufschrift  -in .mittlererRahmen -row 2 -column 0 -sticky sw
grid .bildnameEingabefeld  -in .mittlererRahmen -row 0 -column 1 -sticky we
grid .bildbreiteScale      -in .mittlererRahmen -row 1 -column 1 -sticky we
grid .bildhoeheScale       -in .mittlererRahmen -row 2 -column 1 -sticky we
# Aendern des Fenstertitels:
wm title . "povgui"

Wie geht's weiter?

Im vierten und letzten Teil in Heft 10/2000 fügen wir die Funktionen zu diesem GUI hinzu, darunter den Aufruf eines Dateimanagers, und gestalten Unterprogramme.

Glossar

Widget-Library

Die Zusammenstellung von Funktionen zur Erzeugung von Fensterelementen ("Widgets") wie z.B. Buttons und Menüs.

Interpreter

Interpreter übersetzen ein Programm jedesmal, wenn es aufgerufen wird, in Maschinencode. Die Übersetzung wird anders als bei kompilierten Programmen nicht auf Dauer gespeichert.

Raytracer

Beim Raytracing ("Strahlenverfolgen") wird für jeden einzelnen Bildpunkt ("Pixel") der Strahlengang vom Beobachter (Kamera) zu den Lichtquellen zurück verfolgt. Trifft der Strahl auf ein Objekt, dann versucht der Raytracer, ihm vom Auftreffpunkt ausgehend zu allen Lichtquellen der Szene nach zu gehen. Liegt im weiteren Strahlengang ein zweites Objekt, so wirft dieses einen Schatten auf das erste. Aus all diesen Überprüfungen und der Farbe des Objekts ergibt sich schließlich eine Farbe für den Pixel.

rendern

Erstellen eines Bildes aus mathematischen Daten. Im Falle von Povray werden diese Daten aus einer Szenenbeschreibung generiert.

Pfad

1) Die Zusammenstellung der Verzeichnisse, in der ihre Shell nach ausführbaren Programmen sucht. 2) Die komplette Angabe des Standorts einer Datei innerhalb des Verzeichnisbaums. Der Pfad zur Datei kann relativ, also vom aktuellen Verzeichnis, oder absolut, d.h. vom Wurzelverzeichnis "/" aus angegeben werden.

.

Der Punkt bezeichnet das aktuelle Verzeichnis, in dem Sie sich gerade befinden. Ist dieses nicht explizit im Pfad enthalten, muss es extra angegeben werden, um Programme darin auszuführen.

GUI

"Graphical User Interface", zu deutsch "grafische Benutzeroberfläche". Der Teil des Programms, welches die Nutzer sehen, und über das sie auf die Funktionalität des Programms zugreifen.

Infos

[1] Eine gute Einführung in Povray ist von Christian Perle im Linux-Magazin 04/1998 erschienen. Sie ist auch im WWW erhältlich: http://www.linux-magazin.de/ausgabe/1998/04/Povray/povray.html

[2] Falls Sie Povray noch nicht haben, bekommen Sie es hier: http://www.povray.org/

[3] Tcl/Tk ist zwar bei jeder Distribution dabei, im Source-Code können Sie es aber auch herunter laden bei: http://www.scriptics.com/

[4] John Ousterhout, der "Erfinder" von Tcl/Tk hat selbst ein sehr lesenswertes Buch über Tcl/Tk geschrieben: Ousterhout, John K.: "Tcl und Tk", Addison-Wesley, Bonn 1995

[5] Wenn Sie schon über Tcl/Tk-Grundkenntnisse verfügen, die Sie auf sinnvolle Weise vertiefen möchten, ist folgendes Buch zu empfehlen: Harrison, Mark und McLennan, Michael: "Effektiv Tcl/Tk programmieren", Addison-Wesley, Bonn 1998

[6] Online-Infos bekommen Sie unter anderem bei: http://www.sco.com/Technology/tcl/Tcl.html

[7] Der erste Teil dieser Programmiereinführung ist erschienen im Linux-Magazin 04/2000, S. 120--124 und online abrufbar unter: http://www.linux-user.de/ausgabe/2000/06/TclTk1/tcl1.html

[8] Teil Zwei können Sie nachlesen im Linux-Magazin 06/2000, S. 148--153

[9] Linux-User 06/2000, S. 78--83

Der Autor

Sibylle Nägle macht gerade ihr Maschinenbau-Diplom in Kassel und ist froh, dafür mit Tcl programmieren zu dürfen.

Tip a friend    Druckansicht beenden Bookmark and Share
Kommentare