II. Beispiel: Interaktion mit Buttons
Ziel des Beispiels:
- ein Programm, welches einen vorgegebenen String auf Knopfdruck in der Konsole ausgibt
- ein Programm, welches den Inhalt eines Ausgabefeldes auf Knopfdruck ändert
- Programm, welches auf Knopfdruck den Inhalt eines Eingabe ausliest und anschließend als Konsolenbefehl ausführt
Programm, welches einen vorgegebenen String auf Knopfdruck ausgibt |
- Starten von FLUID.
- Anlegen der "int main()"-Methode durch New -> Code -> function/method. In der Eingabemaske müssen beide Zeilen gelöscht
werden, dadurch legt FLUID die main()-Methode an.
- Inerhalb der main()-Methode wird nun über New -> Group -> Window ein Fenster angelegt. Dies wird das Hauptfenster unserer
Applikation. Durch einen Doppelklick auf das Window-Element in der FLUID-Hierachie (FLUID-Hauptfenster) kann man das Eigenschaften-Menü öffnen
und unter "Label" in der Registrierkarte "Style" einen Fensternamen für das Hauptfenster festlegen.
- Als nächstes wird ein Button gebraucht, diesen legen wir über New -> Buttons -> Button an. Ein Button erfordert ein paar
Einstellungen im Eigenschaftenmenü. In der Registrierkarte "C++" muss im Textfeld "Callback" die Callback-Funktion angegeben
werden, die beim Klick auf den Button ausgeführt werden soll. Hier wird einfach nur der Funktionsname ohne Klammern oder
Semikolon eingegeben, in unserem Beispiel "Button_CB".
Unter "GUI / Label" kann dem Button ein Schriftzug verpasst werden, der dann auf dem Buttons prangt.
- Anschließend muss die Callback-Methode des Buttons "Button_CB" angelegt werden. Dies geschieht über New -> Code -> Method/
Function.
Name(args): (blank for main()):
Hier muss der Name unserer im Button angegebenen Callback-Funktion eingetragen werden, also "Button_CB". Dahinter werden als
Parameter ein FLTK-Objekt und eventuelle Daten (im Moment noch uninteressant) übergeben. In unserem Beispiel heißt der komplette
Funktionsname "Button_CB(Fl_Widget*,void*)".
Achtung: Es dürfen keine Leerzeichen enthalten sein und es wird zwischen
Groß- und Kleinschreibung unterschieden.
Return Type:
Eine Callback-Funktion hat - zumindest in meinen Beispielen - keinen Rückgabetyp, da alle Auswertungen innerhalb der Funktion und des Hauptfenster ausgeführt
werden. Nach FLTK-Vorgaben muss die Funktion trotzdem als statisch deklariert werden.
In unserem Beispiel - wie bei auch bei den meisten Callback-Funktion später auch - muss "static void" eingeben werden.
- Als nächstes brauchen wir den Befehl zur Ausgabe auf der Konsole. Dazu markiert man im FLUID-Hauptfenster die Callback-Funktion
des Buttons und fügt mit New -> Code -> Code ein Stück frei programmierbaren Code ein. Über einen Doppelklick öffnet
sich der Code-Schnipsel zur Bearbeitung.
Der bereits vorhandene Eintrag kann gelöscht werden und kann durch beliebigen Code ersetzt werden. Wir benötigen aber die ganz
normale Ausgabe-Funktion, also trägt man
std::cout<<"How are you?"<<std::endl;
ein.
Achtung: Hier muss korrekter C++-Code stehen, d.h., es muss an alle Semikolons und korrekte Namen gedacht werden. Zur
besseren Lesbarkeit empfiehlt es sich später bei komplexeren Code-Fragmenten den Text mit Hilfe der Tabulator-Taste zu
strukturieren, Stichwort: Bedingungen und Schleifen.
- Eines der Knackpunkte von FLUID ist die C-synchrone Hierachie. In einem C/C++-Programm, das in einer Datei realisiert wird,
gibt es immer den Aufbau:
- Klasseneinbindung (#include <...>)
- Funktionen und Methoden (in unserem Beispiel bisher nur die Button_CB)
- "int main()"-Methode
Bis das Programm bei er Abarbeitung zur main()-Methode gelangt, müssen alle später benötigten Klassen und Methoden initialisiert
worden sein, FLUID behandelt das ganze sehr ähnlich.
Im Hauptfenster von FLUID kann man den Programmaufbau in einer Hierachie sehen und auch hier gilt, dass die Klassen über den
Funktionen und über der main()-Methode stehen. Unsere "Button_CB"-Funktion steht noch unterhalb der "main()"-Methode. Wenn
man im FLUID-Hauptfenster ein Element markiert, kann man es mittels F2 nach oben bzw. mittels F3 nach unten
verschieben.
Auf diese Weise kann man eine C/C++-synchrone Hierachie erstellen.
- Nun steht die Callback-Funktion unseres Buttons über der "main()"-Methode, aber etwas fehlt noch.
Innerhalb des Code-Fragmentes in der Callback-Funktion benutzen wir den "std::cout"-Befehl, für den die Klasse "iostream"
notwendig ist und genau diese muss noch eingebunden werden.
Über New -> Code -> Code Declaration kann eine Zeile Code eingegeben werden, welche für
#include <iostream>
völlig ausreicht. Nicht vergessen, dass die Klasseninitialisierung am Anfang des Programms stehen muss und mittels F2
nach oben verschoben werden kann.
- Damit dürfte unser erstes Beispiel-Programm, welches auf Knopfdruck "How are you?" auf der Linux-Kommando-Zeile bzw. in der
MySys-Umgebung unter Windows ausgibt, fertig sein.
Achtung: Die meisten Makefiles greifen auf .CPP-Dateien zurück, FLUID schreibt standardmäßig .CXX-Dateien. Um dies zu
ändern muss über Edit -> Project Settings das cxx durch ein cpp ersetzt werden.
Jetzt noch unter File -> Write Code die CPP-Dateien erzeugen und wie gehabt kompilieren und ausführen.
Achtung: Es empfiehlt sich das FL-Projekt hin und wieder zu speichern, weil FLUID gelegentlich auch mal astürtzt und
nicht automatisch speichert. Leider kann FLUID aus einer mit FLUID-erstellten C++-Datei kein Projekt rekonstruieren.
- Hinweis: Einer der großen Vorteile von FLUID bestehen darin, dass es möglich ist, die ganze Ausrichtung von
grafischen Elementen in der Vorschau schon einzustellen, in dem man die Elemente einfach in ihrer Größe oder Position
"durch Ziehen" verändert. Dies erspart einem das Jonglieren mit Pixeln für Größe und Position.
Ein Programm, welches den Inhalt eines Ausgabefeldes auf Knopfdruck ändert |
- Die Schritte 1 bis 5 wiederholen sich an dieser Stelle:
- FLUID starten.
- main()-Methode anlegen.
- Fenster als Hauptfenster des Programmes anlegen.
- Button ins Hauptfenster setzen und Callback-Methode mit "Button_CB" bezeichnen.
- Funktion "Button_CB(Fl_Widget*,void*)" anlegen.
- Als nächstes brauchen wir im Hauptfenster ein entsprechenden Ausgabe-Feld. Man marktiert das "Window"-Element innerhalb der main()-Methode
und legt über New -> Text -> Output ein neues Ausgabefeld an, diese Felder sind - wie der Name schon sagt -
ausschließlich für die Ausgabe bestimmt.
- Anschließend ruft man das Eigenschaften-Menü auf und hier kommt wieder einer der Kanckpunkte in FLUID.
Zum einen kann man unter "GUI / Label" (Registrierkarten) den Text vor dem eigentlichen Ausgabefeld bestimmen und zum
anderen - was viel wichtiger ist - muss man unter der Registrierkarte "C++" im Feld "Name" etwas eitragen, bei mir "output".
An dieser Stelle wird ein Pointer auf das Ausgabefeld angelegt mit dessen Hilfe später das Ausgabe-Feld verändert werden kann.
- Nun geht es weiter in der CallBack-Funktion des Buttons, "Button_CB". Hier muss nun ein Befehl eingegeben werden, der den Inhalt
des Ausgabefeldes "output" manipuliert.
Wieder wird über New -> Code -> Code ein Quelltext-Schnippsel innerhalb der CallBack-Funktion eingefügt. Diesmal ändert
sich der Befehl innerhalb des Code-Stückchens in
output->value("How are your?");
dabei ist output der Pointer auf das Ausgabefeld und value ein Pointer auf dessen Wert.
Allgemein kann man sagen, dass Ausgabewerte (auch wenn sie in einem Eingabefeld dargestellt werden), vom Typ const char* sein
müssen.
- Noch Kompilieren und Ausgeben, das war's schon.
Ein Programm, welches auf Knopfdruck den Inhalt eines Eingabe ausliest und anschließend als Konsolenbefehl ausführt |
- Die Schritte 1 bis 5 wiederholen sich an dieser Stelle:
- FLUID starten.
- main()-Methode anlegen.
- Fenster als Hauptfenster des Programmes anlegen.
- Button ins Hauptfenster setzen und Callback-Methode mit "Button_CB" bezeichnen.
- Funktion "Button_CB(Fl_Widget*,void*)" anlegen.
- Es wird jetzt anstatt einem Ausgabefeld ein Eingabefeld benötigt. Also legen wir im "Window"-Element der main()-Methode über
New -> Text -> Input ein entsprechendes Eingabefeld an.
- Im Eigenschaftenmenü muss wieder ein Pointername vergeben werden, in meinem Beispiel soll er einfach nur "input" heißen.
In "GUI / Label" kann wieder ein entsprechender Text eingegeben werden.
- Als nächstes muss die Callback-Methode des Buttons bearbeitet werden und wie in den Beispielen zuvor, muss der über
New -> Code -> Code ein Code-Fragment eingefügt werden.
Der Befehl ändert sich diesmal in:
system(input->value());
Im einzelnen bedeutet dass:
- input->value() holt den aktuellen Wert des Eingabefeldes, wobei input wieder der zuvor übers Eigenschaftemenü des
Eingabefeldes eingegebene Pointername ist.
- system gibt das ganz als Befehl auf der Kommandozeile aus.
- Damit der system-Befehl genutzt werden kann, muss die stdlib.h mit eingebunden werden.
Dies geschieht wie schon im ersten Beispiel über New -> Code -> Declaration. Dann einfach noch in die Zeile
#include
eingeben und das Programm ist fertig.
- Es folgt das Kompilieren und Ausführen, zum Testen sollte man anfangs harmlosere Konsolenbefehle wie "dir" ausprobieren.