| Das R-BASIC Handbuch im HTML-Format |
| Startseite > R-BASIC > Das R-BASIC Handbuch im HTML-Format |
|
|
Das R-BASIC ProgrammierhandbuchEinfach unter PC/GEOS programmierenAutor: Rainer BettstellerHTML-Version: Mütze - Hinweise & Fehler an |
Ein Anfänger-TutorialDieses Tutorial beschreibt an einem einfachen Beispiel, wie man ein R-BASIC Programm erstellt. Dabei werden viele Fakten und Zusammenhänge einfach benutzt, ohne sie ausführlich zu erklären. Stattdessen gibt es jeweils Verweise auf die Kapitel im Handbuch, wo Sie weiterführende Erklärungen finden. Einige Begriffe sind fett markiert. Diese Begriffe kommen im Handbuch immer wieder vor. Eine exakte Erklärung dieser Begriffe finden Sie im nächsten Kapitel.Die Schrittfolge, die hier dargestellt wird, können Sie prinzipiell auf jedes Programm anwenden.
1. Der Plan ...Als Einstieg wollen wir uns ansehen, wie man das folgende Programm erstellt. Der Nutzer soll eine Zahl eingeben und das Programm soll prüfen, ob die Zahl gerade ist oder nicht.^2. Die UI (das User-Interface)Das Erstellen eines Programms beginnt in den allermeisten Fällen mit der Programmierung der Benutzeroberfläche, der UI. Das heißt, Sie legen fest welche Objekte es gibt und wie sie angeordnet sind.
Jedes Objekt hat einen Typ, der Programmierer sagt, es gehört einer Klasse an. Die Klasse bestimmt die Eigenschaften und Fähigkeiten eines Objekts. Die in R-BASIC verfügbaren Klassen und deren Eigenschaften sind im "Objekt-Handbuch" beschrieben. Es ist durchaus vernünftig, sich zunächst eine Zeichnung anzufertigen. So kann man sich überlegen, wie die Programmoberfläche ungefähr aussehen könnte und wie viele und welche Objekte man benötigt. Außerdem kann man den wichtigsten Objekten jetzt schon einen aussagekräftigen Namen geben.
Prinzipiell sind Sie in der Wahl des Namens frei, es hat sich jedoch bewährt, den Namen aus zwei Teilen zusammenzusetzen. Der erste Teil beschreibt das Programm oder den Programmteil, zu dem das Objekt gehört. In unserem Fall wählen wir "Tutor". Der zweite Teil bezeichnet die Klasse, zu der das Objekt gehört. Das Primary Objekt heißt daher TutorPrimary, der Button heißt TutorButton usw. Das Datei-Menü ist auch ein Objekt. Es wird aber vom Primary-Objekt automatisch erzeugt, so dass wir uns darum nicht kümmern müssen. Für unser Programm benötigen also wir 5 Objekte:
In unserem Fall sieht die Verbindung, der sogenannte Objekt-Tree (Objektbaum), wie folgt aus. Zum Beispiel ist das Objekt TutorNumber ein child (Kind) des Objekts TutorPrimary. Im Gegenzug ist das Objekt TutorPrimary das parent (Eltern) des Objekts TutorNumber.
Es ist ganz wichtig, dass alle Objekte in den Objekttree eingebunden sind. Dazu gibt es die Anweisung "Children". Vergessen Sie das Einbinden eines Objekts in den Tree, so wird das Objekt nicht auf dem Bildschirm erscheinen. Es gibt darüber keine Fehlermeldung, da Sie nichts Verbotenes getan haben. Alle Objekte werden im UI-Codefenster vereinbart. Das Application-Objekt hat genau ein Child, des Primary-Objekt. |
Application TutorApplication Children = TutorPrimary End OBJECT |
|
Um ein Objekt anzulegen müssen Sie nicht jede Zeile einzeln tippen. Öffnen Sie stattdessen das Menü "Extras" -> "Code-Bausteine" -> "Neues Objekt". Dort finden Sie das Application-Objekt und auch alle anderen von uns benötigten Objekte. Sie brauchen nur noch die programmspezifischen Dinge ergänzen. Das Application-Objekt wird von uns nicht als Child eines anderen Objekts gesetzt, darum kümmert sich das System.
Nun legen wir das Primary-Objekt an und binden es in den Tree ein. Haben Sie daran gedacht, das Menü "Extras" -> "Code-Bausteine" -> "Neues Objekt" zu verwenden, um das Primaryobjekt anzulegen? Nachdem Sie das Objekt angelegt haben erscheint automatisch ein Dialogbox, die Sie beim Einbinden des Objekts in den Tree unterstützt.
Unser Primary-Objekt soll drei Children haben: das Number-Objekt, den Text und den Button. Es ist unter GEOS nicht üblich die Position der Objekte explizit anzugeben. Stattdessen geben wir an, wie die Objekte angeordnet werden sollen. Details zu diesem Thema finden Sie im Kapitel 3.3 (Geometriemanagement) des Objekt-Handbuchs. Wir wollen, dass die Children horizontal zentriert sind (justifyChildren = J_CENTER). JustifyChildren ist eine Instancevariable des Primaryobjekts. Instancevariablen können unterschiedliche Werte annehmen. In unserem Fall weisen wir ihr den Wert J_CENTER zu. J_CENTER ist eine numerische Konstante, d.h. J_Center steht symbolisch für eine Zahl. Die UI-Anweisung SizeWindowAsDesired bewirkt, dass das Primary nur so groß ist, wie unbedingt nötig. Probieren Sie ruhig aus, was passiert, wenn Sie eine oder mehrere dieser Zeilen auskommentieren (Ausrufezeichen davor schreiben). |
Primary TutorPrimary Children = TutorNumber, TutorText, TutorButton justifyChildren = J_CENTER SizeWindowAsDesired End OBJECT |
| Für das Number-Objekt setzen wir zur Demonstration ein paar Instancevariablen. Die Instancevariable Caption$ enthält Text, der das Number-Objekt näher beschreiben soll. Er erscheint direkt neben oder auf dem Objekt. Außerdem legen wir einen Startwert (value) sowie einen Minimal- und einen Maximalwert (minVal, maxVal) fest. Unser Numberobjekt stellt nur ganze Zahlen dar. Im Kapitel 4.7.2 (Display-Format) des Objekt-Handbuchs ist beschrieben, wie man Numberobjekte konfiguriert, damit sie Dezimalstellen darstellen können. |
Number TutorNumber Caption$ = "Zahl eingeben:" value = 12 minVal = -100 maxVal = 100 End OBJECT |
| Das Ergebnis unserer Prüfung wollen wir in ein Textobjekt schreiben. Da der Nutzer dort nichts eingeben soll setzen wir das Textobjekt auf "nur Lesen", d.h. wir weisen der Instancevariablen readOnly den Wert TRUE zu. TRUE ist wieder eine numerische Konstante. Die UI-Anweisung TextFrame erzeugt einen Rahmen um das Objekt, der sonst bei read-only Objekten fehlt. Da wir noch keine Prüfung vorgenommen haben setzen wir als Anfangswert für den darzustellenden Text das Wort "ungetestet". Schließlich bewirkt die UI-Anweisung justifyText = J_CENTER, dass der Text zentriert dargestellt wird. Eine ausführliche Beschreibung der Textobjekte finden Sie im Kapitel 4.10 des Objekt-Handbuchs. |
Memo TutorText text$ = "ungetestet" readOnly = TRUE TextFrame justifyText = J_CENTER End OBJECT |
|
Schließlich brauchen wir noch einen Button, mit dem wir die Prüfung der Zahl starten. Wenn wir den Button aktivieren wird eine spezielle Routine, der Actionhandler des Buttons, gestartet. Die Anweisung ActionHandler = CheckNumber legt fest, dass die Routine "CheckNumber", die wir noch schreiben müssen, gestartet werden soll, wenn wir den Button aktivieren. Button-Objekte sind im Kapitel 4.3 des Objekt-Handbuchs beschrieben.
Die Null in der Caption$ - Zeile legt fest, dass der Buchstabe an Position Null (hier das 'P') unterstrichen und zur Tastaturnavigation benutzt werden soll. |
Button TutorButton Caption$ = "Prüfen", 0 ActionHandler = CheckNumber End OBJECT |
^3. Der ActionhandlerNun müssen wir noch den Actionhandler des Buttons schreiben. Actionhandler sind spezielle Routinen, die direkt von einem Objekt aufgerufen werden. Actionhandler, die von einem Button aufgerufen werden, müssen als BUTTONACTION vereinbart werden. Auch hier benutzen wir das Menü "Extras" -> "Code-Bausteine" um den Actionhandler anzulegen (Unterpunkt "Action-Handler"). |
BUTTONACTION CheckNumber
DIM z ' z: zahl
z = TutorNumber.value
IF z/2 = Int(z/2) THEN
TutorText.text$ = "gerade"
ELSE
TutorText.text$ = "ungerade"
END IF
END ACTION
|
|
Die Zeile "z = TutorNumber.value" ist eine Zuweisung. Sie liest den Zahlenwert (value) des Numberobjekts aus und speichert ihn in der Variablen z. Man sagt, der Variablen z wird ein Wert zugewiesen. Z muss vorher mit DIM vereinbart worden sein.
Mit der IF-Anweisung können wir Entscheidungen treffen. Ist der zwischen IF und THEN stehende Ausdruck wahr, so werden die Anweisungen hinter THEN ausgeführt (in unserem Fall ist es nur eine Anweisung), andernfalls die hinter ELSE. End IF schließt den Entscheidungsteil. Das Kapitel 2.5.1 (Verzweigungen) des Programmierhandbuchs beschreibt die Möglichkeiten von R-BASIC, Entscheidungen zu treffen. Um festzustellen, ob die Zahl gerade ist vergleichen wir die Hälfte der Zahl (z/2) mit dem ganzzahligen Anteil (Funktion Int(..)) der halben Zahl. Ist zum Beispiel z = 5, so ist z/2 = 2,5 und Int(z/2) = 2. Die Werte sind nicht gleich, z ist ungerade. Einen Überblick über die in R-BASIC verfügbaren mathematischen Funktionen finden Sie im Kapitel 2.3.1 (Überblick über numerische Funktionen) des Programmierhandbuchs. Die Anweisung TutorText.text$ = "...." weist dem Textobjekt einen neuen Text zu, der sofort angezeigt wird. Zeichenketten (genannt Strings) werden in " " eingeschlossen, Stringvariablen werden üblicherweise durch ein angehängtes $ gekennzeichnet. Das ist Ihnen bestimmt schon bei Caption$ aufgefallen.
Nachdem Sie das Programm eingetippt und gestartet haben sollten Sie damit herumspielen. Ändern Sie einzelne Codezeilen oder kommentieren Sie sie aus. Überlegen Sie vorher, was passieren wird und vergleichen Sie Ihre Vorhersagen mit dem erreichten Ergebnis.
4. Erste VerbesserungenWir wollen nun unser Programm etwas verändern, indem wir die Eingabe der Zahl nicht über ein Numberobjekt, sondern über ein Textobjekt machen. Das sieht besser aus und "Drag'n Drop" funktioniert auch.
Dazu verwenden wir die andere Textobjektklasse, über die R-BASIC verfügt. Das Objekt InputLine stellt einen einzeiligen Text bereit. Mit der Anweisung "justifyCaption = J_TOP" verschieben wir die Aufschrift über das Objekt. Captions sind sehr vielseitig. Sie können nicht nur Text sondern auch Grafiken enthalten. Details dazu finden Sie im Kapitel 3.1 (Caption: Die Objekt-Beschriftung) des Objekt Handbuchs. |
InputLine TutorInputText Caption$ = "Zahl eingeben:" justifyCaption = J_TOP text$ = "12" backColor = WHITE textFilter = TF_SIGNED_NUMERIC + TF_NO_SPACES End OBJECT |
|
Der Startwert (text$ = "12") ist natürlich keine Zahl, sondern ein String. Mit "backColor = WHITE" machen wir den Texthintergrund weiß. WHITE ist eine numerische Konstante (ein Symbol für eine Zahl). R-BASIC hat für alle 16 Standardfarben eine entsprechende Konstante. Näheres zur Beschreibung von Farben finden Sie im Kapitel 2.8.2 (Farben) des Programmierhandbuchs.
Von besonderer Bedeutung ist für unsere Anwendung die Zeile "textFilter = TF_NUMERIC + TF_NO_SPACES". Textfilter sind eigentlich etwas für Fortgeschrittene, aber an dieser Stelle sehr hilfreich. Ein Textfilter weist das Objekt an, nur bestimmte Zeichen zu akzeptieren. In unserem Fall sind die Werte TF_SIGNED_NUMERIC (nur Ziffern, Minus und Leerzeichen) kombiniert mit TF_NO_SPACES (keine Leerzeichen) angebracht. Das Setzen eines Textfilters erspart uns bei der Auswertung die Aufwändige Prüfung, ob der Nutzer überhaupt eine Zahl und nicht etwa "Paul" oder "eins" eingegeben hat. Textfilter sind im Kapitel 4.10.5 (Textfilter) des Objekthandbuchs beschrieben. Bitte vergessen Sie nicht, das neue Objekt anstelle des Number-Objekts als Child des Primary-Objekts einzutragen. Natürlich müssen wir jetzt unsere Auswerteroutine anpassen. Insbesondere müssen wir den vom Nutzer eingegebenen Text in eine Zahl umwandeln. Diese Aufgabe erledigt die Funktion Val(...). Val steht für das englische Wort value (Wert). "t$ = TutorInputText.text$" speichert zuvor den vom Nutzer eingegeben Text in der Stringvariablen t$. Die DIM-Anweisung erkennt an dem angehängten $-Zeichen, dass die Variable einen Text und keine Zahl aufnehmen soll. |
BUTTONACTION CheckNumber
DIM z, t$' zahl, text
t$ = TutorInputText.text$
z = Val(t$)
IF z/2 = int(z/2) THEN
TutorText.text$ = "gerade"
ELSE
TutorText.text$ = "ungerade"
END IF
END ACTION
|
| Tipp: Da die Variable t$ nirgends weiter gebraucht wird kann man sie auch einsparen. Die ersten beiden Zeilen werden dann zu: |
z = Val( TutorInputText.text$ ) |
Details zu Variablen und den zugehörigen Datentypen finden Sie weiter unten, im Kapitel 2.2 (Variablen und Typen). Der leichte Umgang mit Zeichenketten (Strings) gehört zu den großen Stärken der BASIC-Syntax. Einen Überblick über die in R-BASIC zur Verfügung stehenden Stringfunktionen finden Sie im Abschnitt 2.4.1 des Programmierhandbuchs.
^5. Weitere ÄnderungenNun möchten wir die am Anfang eingestellte Zahl durch eine zufällig ausgewählte Zahl ersetzen. Dazu benötigen wir eine Routine, beim Programmstart automatisch ausgeführt wird. Das ist eine sehr häufig auftretende Situation. In R-BASIC ist das so gelöst, dass wir dem Application-Objekt einen "OnStartup" Handler geben. Wir nennen ihn "AppStartup". Wir hätten ihn auch "Paul" nennen können, aber die Namenswahl AppStartup enthält gleichzeitig einen Hinweis darauf, was der Handler tun soll. Das ist prinzipiell immer eine gute Idee. Der UI-Code des Application-Objekts sieht jetzt also so aus: |
Application TutorApplication Children = TutorPrimary OnStartup = AppStartup End OBJECT |
|
Das Application-Objekt ist im Kapitel 4.1 des Objekthandbuchs beschrieben. Es bietet zum Beispiel die Möglichkeit einem Programm ein eigenes Token (Icon) zu geben und vieles mehr.
Unser AppStartup Handler muss als SYSTEMACTION vereinbart werden. Je nachdem, ob wir das Number-Objekt TutorNumber oder das InputLine-Objekt TutorInputText zur Eingabe der Zahl verwenden fällt der Handler geringfügig anders aus. Wir schauen uns zunächst die Variante mit dem Number-Objekt an. |
' Variante mit Number-Objekt SYSTEMACTION AppStartup DIM z' zahl Randomize z = Int( 100 * Rnd() ) TutorNumber.value = z END ACTION |
|
Als erstes initialisieren wir mit der Anweisung Randomize den Zufallsgenerator. Das sollte jedes Programm, das mit Zufallszahlen arbeitet, tun.
Die Funktion Rnd() liefert eine Zufallszahl x im Bereich 0 <= x < 1. Wenn wir unsere Zufallszahl z im Bereiche 0 <= z < 100 haben wollen müssen wir diesen Wert mit 100 multiplizieren. Die Funktion Int() (Int steht für Integer, ganzzahlig) schneidet die Nachkommastellen ab. Die Zeile z = Int( 100 * Rnd() ) weist also der Variablen z eine Ganze Zahl im Bereich zwischen 0 und 99 zu. Schließlich weisen wir mit der Anweisung TutorNumber.value = z dem Objekt TutorNumber den Wert der Variablen z zu. Das Objekt zeigt diesen Wert sofort an. Wenn wir das Textobjekt zur Eingabe der Zahl verwenden sieht der Handler so aus: |
SYSTEMACTION AppStartup DIM z' zahl Randomize z = Int( 100 * Rnd() ) TutorInputText.text$ = Str$(z) END ACTION |
|
Wir sehen, dass sich nur die letzte Zeile unterscheidet. Zunächst heißt die Instancevariable, die wir belegen müssen, bei einem Textobjekt "text$". Diese enthält natürlich eine Zeichenkette (einen String) und keine Zahl. Deswegen müssen wir die Zahl z mit der Funktion Str$() in eine Zeichenkette umwandeln.
Das ist schon alles.
Zusammenfassung
Tipps
^ |