Ein erstes “Hello World” von JavaFX mit Maven
https://bildung.social/@oerinformatik/
https://oer-informatik.de/jfx_02_helloworld_und_aufbau
tl/dr; (ca. 5 min Lesezeit): Aufbau einer “Hello World”-JavaFX App und Analyse der beteiligten Klassen, Objekte und Methoden. Hintergrund zum Aufruf der Methoden
launch()undstart(), die den Start einer JavaFX-App bilden. Der Artikel ist Teil eines JavaFX-Tutorials. (Zuletzt geändert am 19.11.2023)
Änderungen am Programmcode…
Wir haben in unserem Ausgangsprogramm drei Dateien und eine Ordnerstruktur erzeugt:
Die
pom.xmllegt fest, welche Abhängigkeiten wir laden (z.B. die JavaFX-Module), mit welcher Java-Version wir unser Projekt starten wollen, wie das Projekt und das umgebende Paket heißt und wo die Startklasse zu finden ist. Abhängigkeiten und Java-Version mussten wir gegenüber der Vorlage anpassen.Die Startklasse hört im Beispiel auf den Namen “App.java” und liegt in der Ordnerstruktur, die dem Paketnamen entspricht (
src/main/java/de/csbme/ifaxx/myfxproject/App.java). Beides könnten wir in derpom.xmlanpassen (tut aber nicht Not). Wir hatten hier zwei Änderungen vorgenommen: in dermain()-Methode wurde ein Aufruf ergänzt (launch()) und eine zweite Methode (start()) wurde eingefügt, um die wir uns hier genauer kümmern werden.Die
AppTest.java, die unsere Vorlage erzeugt hat, referenziert noch auf die Beziehnungen einer alten jUnit-Version - im einfachsten Fall leeren wir diese Datei bis auf den Klassenrumpf und die Package-Bezeichnung.
Wer eine andere Vorlage verwendet hat, hat ggf. einen andern Startklassennamen, andere Pakete und Dateien wie primary.fxml, secondary.fxml oder module-info.java - die wir hier nicht benötigen - diese können gelöscht werden.
Anpassungen in der Datei App.java
In der pom.xml wurde ja bei der Konfiguration von main.class hinterlegt, wie die Klasse heißt, die unser Artefakt startet (in diesem Fall: unsere Desktop-App App.java).
Maven startet in dieser Klasse eine public static void main(String[] args)-Methode. Für das Grundgerüst benötigen wir also diese statische Methode.
Damit wir nicht alle Methoden selbst implementieren müssen, nutzen wir eine vordefinierte JavaFX-Klasse, von der wir erben: public class App extends Application.
Eine zweite Methode namens start() benötigt JavaFX, um später unser eigentliches Programm aufzunehmen. Das Grundgerüst der App.java sollte also etwa so aussehen:
package de.csbme.ifaxx.myfxproject;
/*Imports*/
public class App extends Application {
@Override
public void start(Stage primaryStage){
/*Implementierung*/
}
public static void main(String[] args) {
launch(args);
}
}Jetzt können wir die Platzhalter in der App.java füllen. Die Methode start() ist das Herzstück unseres ersten eigenen JavaFX-Programms. Hieran können wir die Grundlagen eines jeden JavaFX-Programms erkennen. In unserem Ausgangsbeispiel gab es nur zwei Zeilen in dieser Methode (primaryStage.setScene(...); und primaryStage.show()). Wir ersetzen diese beiden Zeilen durch einen etwas detaillierteren und übersichtlicheren Aufruf:
@Override
public void start(Stage primaryStage){
Text textLeaf = new Text("Hallo");
StackPane rootNode = new StackPane(textLeaf);
Scene scene = new Scene(rootNode, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}Wir schauen uns die Methode mal von unten nach oben an:
Die Stage erhalten wir als Parameter übergeben, von wem genau schauen wir uns später an. Die Stage ist der Ort, an dem alles angezeigt wird - das Startfenster unseres Programms. Wir zeigen diese am Ende der Methode mit primaryStage.show(); an.
Die Dinge, die wir auf der Bühne anzeigen, nennen wir Scene - also Szenen (primaryStage.setScene(scene);). In unserem Beispiel ist die Scene 300x200 Pixel groß und zeigt etwas an, das hier rootNode genannt wurde (new Scene(rootNode, 300, 250);).
Ein Node ist ein Inhaltselement, das weitere Inhaltselemente enthalten kann (z.B. eine Tabelle, ein Gitter, ein Stapel). In unserem Fall enthält der Stapel (StackPane) nur ein Element, nämlich einen Text (new StackPane(textLeaf);). Diesen Text haben wir in der ersten Zeile der Methode erstellt (Text textLeaf = new Text("Hallo");).
Was jetzt noch fehlt, um ein lauffähiges Programm zu erhalten, sind die fehlenden Importe. Wenn es die IDE nicht alleine schafft, die korrekten Klassen zu finden, dann hilft vielleicht dieser Spickzettel zum Vergleichen:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;Wer ruft hier eigentlich wen auf?
Es scheinen bei JavaFX wieder von Zauberhand Dinge zu passieren, die schwer nachvollziehbar sind: In der main()-Methode wird eine launch()-Methode aufgerufen, die nirgends implementiert ist. Stattdessen gibt es eine start()-Methode, die wiederum nirgends aufgerufen wird. Wir müssen hier kurz Licht ins Dunkel bringen, in dem wir uns mal ein UML-Klassendiagramm anschauen:

Das erste Geheimnis ist schnell gelüftet: die mysteriöse Methode launch()-Methode, die in der main()-Methode aufgerufen wird, ist eine statische Methode der Superklasse Application, von der App erbt.
Das zweite Rätsel bleibt aber: start() ist eine Instanzmethode. Aber an welcher Stelle wird eine Instanz von App gebildet? Und wo wird start() aufgerufen?
Dazu werfen wir ein Blick in ein UML-Sequenzdiagramm, das die Abläufe im Hintergrund etwas erklärt:

Der Benutzer startet Maven, Maven wiederum ruft die
main()-Methode der in derpom.xmlhinterlegten Klasse (hier:App) auf. Das hatten wir ja bereits entschlüsselt.In dieser Main-Methode wird
launch()aufgerufen, eine statische Methode der SuperklasseApplication. Diese wiederum ruft eine statische Methode einer weiteren Klasse auf (muss man sich nicht merken, der Vollständigkeit halber: sie heißtLauncherImpl):Der Dreh- und Angelpunkt ist die
launchApplication()-Methode dieser mysteriösen Klasse (LauncherImpl). Diese Methode erzeugt die Stage, auf der später alles angezeigt wird, instanziiert die KlasseAppund ruft schlussendlich diestart()-Methode auf, die dann wiederum die Stage selbst anzeigt (show()). Bei Programmende wird hier noch die Methodestop()derAppaufgerufen.
Vielleicht war das für jetzt etwas dick aufgetragen. Ich komme jedoch häufig an den Punkt, an dem ich Dinge erst verstehe (und debuggen kann), wenn mir die dahinterliegende Struktur klar geworden ist. Wer noch etwas mehr über die Hintergründe und Realisierungen erfahren will, der kann sich den Quelltext der Superklasse Application sowie der Klasse LauncherImpl unter diesen Links ansehen.
Ausführen des JavaFX-Projekts
Eigentlich haben wir nur den Code umgeschrieben, ohne großartig neue Funktionen zu implementieren. Trotzdem: per Maven/Plugins/javafx/run oder per Konsole können wir das Programm starten:
Nächste Schritte
Ein leeres Projekt ist kein schönes Projekt. Wir brauchen Struktur und dazu den Scenegraph (siehe folgender Artikel).
Dieser Artikel ist ein Teil der Artikelserie zu einer Energiemonitors mit JavaFX.
Links und weitere Informationen
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Ein erstes "Hello World" von JavaFX mit Maven” von Hannes Stein, Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/jfx_02_helloworld_und_aufbau veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/javafx/javafx-einstieg. Stand: 19.11.2023.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
