Unsere ersten JavaFX-Anwendung
Beispiel 1: Ein Fenster mit einem Label
Sehen wir uns ohne große Umschweife direkt ein Beispiel an:
import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; public class ErstesFX extends Application { @Override public void start(Stage meineStage) throws Exception { meineStage.setTitle("Erstes FX"); final BorderPane root = new BorderPane(); final Label meinLabel = new Label("Hallo FX!"); root.setCenter(meinLabel); final Scene meineScene = new Scene(root, 200, 100); meineStage.setScene(meineScene); meineStage.show(); } public static void main(String[] args) { launch(args); } }
Dieses Beispiel öffnet ein kleines Fenster, in dem mittig der Text „Hallo FX“ steht. Wie dieses Programm genau aufgebaut ist, gehen wir nun Schritt für Schritt durch, um eine grobe Vorstellung vom Aufbau einer JavaFX-Anwendung zu gewinnen. Weitere Details folgen noch.
- Ganz oben sehen wir, dass einige Klassen importiert werden müssen, die alle im Paket javafx liegen.
- Unsere Anwendung besteht aus der Klasse ErstesFX, die wiederum eine Unterklasse von Application (genau von javafx.application.Application) ist.
Merke: Eine JavaFX-Anwendung benötigt immer eine Unterklasse von Application als Einstiegspunkt. - Unsere Klasse überschreibt die Methode start, die immer ein Objekt der Klasse Stage (genauer: javafx.stage.Stage) als Parameter übergeben bekommen muss.
- Unsere Klasse wirft eine Exception.
- Mit
meineStage.setTitle("Erstes FX");
wird der Titel des Programmfensters festgelegt. - Mit
final BorderPane root = new BorderPane();
wird das grundlegende Layout unseres Fensters festgelegt. Grob gesprochen, wird es damit in fünf Gebiete aufgeteilt: Top, bottom, left, right und center. - Die Anweisung
final Label meinLabel = new Label("Hallo FX!");
erzeugt ein Label, das den Text enthält, den wir schließlich auf dem Bildschirm sehen. Ein Label ist immer dazu da, Text anzuzeigen. - Unserem Layout wird mit
root.setCenter(meinLabel);
das Label hinzugefügt. - In der Zeile
final Scene meineScene = new Scene(root, 200, 100);
wird festgelegt, welches Layout in der Szene meineScene angezeigt werden sollen. Das ist in diesem Fall einfach unser oben definiertes Layout. Theoretisch könnte man mehre Szenen definieren und damit je nach Bedarf wechselnde Inhalte in einem Fenster anzeigen. Das wird hier aber nicht gemacht, womit die Zeile möglicherweise etwas unverständlich wirkt. - Mit
meineStage.setScene(meineScene);
wird festgelegt, dass die eben definierte Szene dargestellt werden soll. Wie eben erklärt, könnte man im Laufe der Anwendung mit diesem Befehl auch zu anderen Szenen wechseln. - Die Anweisung
meineStage.show();
bewirkt, dass unser Programmfenster überhaupt angezeigt wird. - Die main-Methode ruft unmittelbar die launch-Methode der Klasse Application auf. Unsere Anwendung würde auch ohne die main-Methode funktionieren, da die launch-Methode ohnehin automatisch ausgeführt wird. Allerdings wird empfohlen, die main-Methode in dieser Weise einzufügen, damit die exportierte Anwendung (d.h. die .jar-Datei) später auch sicher startet.
Beispiel 2: Ein Button mit Funktion
Wir fügen unserem Beispiel von oben nun noch einen Button hinzu, da unsere Anwendung sonst natürlich sehr langweilig ist.
Hier gibt es neben dem Label im Gebiet center auch einen Button, der im Gebiet bottom hinzugefügt wurde. Anfangs ist das Label noch leer. Nach einem Klick auf den Button wird der Text angezeigt.
Die Änderungen sind mit Kommentaren markiert:
import javafx.application.Application; // Klasse ActionEvent wird importiert. import javafx.event.ActionEvent; // Klasse EventHandler wird importiert. import javafx.event.EventHandler; import javafx.stage.Stage; import javafx.scene.Scene; // Klasse Button wird importiert. import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; public class ErstesFX extends Application { @Override public void start(Stage meineStage) throws Exception { meineStage.setTitle("Erstes FX"); final BorderPane root = new BorderPane(); // Label ist anfangs leer. final Label meinLabel = new Label(""); root.setCenter(meinLabel); // Neues Objekt Button meinButton = new Button ("Klick mich!"); root.setBottom(meinButton); final Scene meineScene = new Scene(root, 200, 100); meineStage.setScene(meineScene); meineStage.show(); // Ereignissteuerung meinButton.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() { public void handle(ActionEvent meinEvent) { meinLabel.setText("Hallo FX!"); } }); } public static void main(String[] args) { launch(args); } }
Wie die Ereignissteuerung genau funktioniert sehen wir uns in der entsprechenden Lektion noch an. Dieses Beispiel kannst Du aber schon mal als Vorlage zum Experimentieren verwenden 🙂
Aufbau des Fensters
Bühne und Szene
Sehen wir uns einmal an, wie wir uns den Aufbau des Fensters in unserem zweiten Beispiel vorstellen können:
Wir können uns grob vorstellen, dass unsere gesamte Anwendung auf einer Bühne („Stage“) präsentiert wird. Auf so einer Bühne können wir eine Szene („Scene“) darstellen.
Wie in einem Theater könnte man auch zu einer anderen Szene wechseln. Zum Beispiel könnten wir einen Vokabeltrainer programmieren, der für das Eingeben neuer Vokabeln und das Trainieren von Vokabeln verschiedene Szenen – d.h. verschiedene Fensterlayouts – hat.
In einer Szene können wir eine grundlegende Struktur des Layouts angeben. In unserem Beispiel haben wir das Layout BorderPane verwendet. Genauer gesagt, haben wir mit final BorderPane root = new BorderPane();
ein Objekt der Klasse BordePane erstellt und mit dem Befehl final Scene meineScene = new Scene(root, 200, 100);
als die Wurzel unserer Szene festgelegt. Woher der Begriff Wurzel kommt, sehen wir uns weiter unten an. Auch zu alternativen Layouts neben BorderPane gehen wir später noch ein!
In dem Layout BorderPane wird – wie oben kurz erwähnt – die Fensterfläche in fünf Teile aufgeteilt: Center, top, right, bottom und left. Mit den Befehlen setCenter, setTop, etc. können wir festlegen, welche Fensterelemente in den verschiedenen Teilen abgelegt werden sollen. Beispielsweise haben wir im ersten Programm mit root.setCenter(meinLabel);
unser Label in die Mitte gesetzt.
Die fünf Teile des Layouts BorderPane können selbst wiederum Layouts enthalten. Dadurch können wir ein Fenster sehr frei gestalten. Dieses verschachteln von Layouts stellt man sich mithilfe des sogenannten Scene Graph vor, den wir uns nun ansehen.
Scene Graph
Die Komponenten unseres Fensters werden in einer Baumstruktur verwaltet. Das bedeutet, dass es als Wurzel eine Hauptkomponente gibt, die weitere Komponenten enthalten kann. In unserem Beispiel ist dies das Objekt root der Klasse BorderPane. Es enthält das Label und den Button, so dass der Graph hier recht simpel aufgebaut ist:
Wie oben schon erwähnt, können einige Komponenten aber selbst erneut Komponenten enthalten, so dass sich eine komplexere hierarchische Struktur ergeben kann:
Ein Baum in der Informatik besteht aus sogenannten Knoten. Den obersten Knoten eines solchen Baumes nennt man die Wurzel. Jeder Knoten kann verschiedene Kindknoten besitzen, die ihm direkt untergeordnet sind. Knoten, die noch weitere Kindknoten besitzen, nennt man Verzweigungen. Knoten, die keine weiteren Kindknoten besitzen, nennt man dagegen Blätter.
Auch wenn wir mit diesen Begriffen nicht allzu häufig in Kontakt kommen werden, ist das Konzept eines Baums hilfreich, wenn wir komplexere Layouts in einem Fenster erstellen möchten.
Runnable JAR – Erstellen einer eigenständigen Anwendung
Sehr erfreulich ist, dass unsere JavaFX-Anwendungen eigenständig (also ohne Eclipse oder ähnliches) auf im Grunde jedem Rechner gestartet werden können. Dazu müssen wir unsere Anwendungen exportieren.
Mit Eclipse geht das so:
- Zuerst gehen wir im Menü auf Datei – exportieren (bzw. File – export).
- Es erscheint ein solches Menü, in dem wir Java – Runnable JAR file wählen müssen.
- Klicken wir auf Next, erhalten wir ein Menü, in dem wir die Hauptklasse unserer Anwendung wählen müssen. Das ist die Datei, die gestartet werden soll. Da unsere Anwendungen momentan ohnehin immer nur aus einer einzigen Datei bestehen, müssen wir einfach genau diese auswählen. Außerdem müssen wir noch angeben, wo die Anwendung gespeichert werden soll.
- Klicken wir auf Finish, wir eine JAR-Datei erstellt. Diese kann auf jedem Rechner auf dem Java installiert ist gestartet werden!
Toller Unterricht weiter so!!! Super!
lol xd
Echt guter Unterricht!
Hallo Herr Dr. Appel;
Ich bin Sven Brodowski aus Heilbronn und bin mittlerweile 56 jahre alt
Ihre Unterlagen sind wirklich excellent richtig gut.
Jedoch habe ich eine Frage !
Das Schlüsselwort final ist nicht ganz klar?
MFG Sven Brodowski
Hallo!
Die Bedeutung von final wird hier erläutert: https://drdanielappel.de/informatik/mein-kleines-java-tutorium/2-einstieg-in-die-objektorietierte-programmierung/2-09-unveraenderliche-attribute-und-konstanten/
Ich hoffe, das hilft weiter!
Schöne Grüße und weiter viel Erfolg beim Programmieren!