3.01 Einführung

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);                
    }

}
Ein Fenster mit dem Text „Hallo FX!“
So sieht unsere Anwendung unter Linux aus.

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

Eine Anwendung mit Label und Button.
Die Schrift erscheint erst nach Klicken des Buttons.

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:

Die Stage enthält eine Scene. Diese enthält die BorderPane, welche wiederum Label und Button enthält.
Eine schematische Darstellung unseres Fensters.

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!

Das Fenster wird in die fünf Teile aufgeteilt.
Aufteilung der Fläche im Layout BorderPane.

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:

Ein Baum mit einer Wurzel und zwei Kindknoten.
Unser Scene Graph ist recht übersichtlich.

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 mit mehreren Knoten.
Die Komponenten werden in einer Hierarchie angeordnet.

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.

    Exportmenü
    Anklicken zum Vergrößern!

  • 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.

    Menü für die Hauptklasse.
    Anklicken zum vergrößern!

  • Klicken wir auf Finish, wir eine JAR-Datei erstellt. Diese kann auf jedem Rechner auf dem Java installiert ist gestartet werden!

5 Gedanken zu „3.01 Einführung“

  1. 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

Kommentare sind geschlossen.