Ein einfaches Hello-World-Fenster mit JavaFX v.7.0

JavaFX ist eine Bibliothek zur Erzeugung von clientseitigen Rich-Internet-Applications. Das Beispiel zeigt ein Fenster, in dem nach Klick auf einen Button der Text HalloWelt auf einem Label erscheint.

Die Hauptklasse eines JavaFX-Programms erweitert die abstrakte Klasse javafx.application.Application. Sie stellt das Umfeld dar, in dem eine JavaFX-Anwendung erstellt und ausgeführt wird. Im Vergleich mit einer konventionellen Java-Anwendung fällt auf, dass in main(), dem Einstiegspunkt jeder Java-Anwendung, lediglich ein Aufruf einer Methode launch() erscheint, der die eventuell beim Start mitgegebenen Kommandozeilen-Parameter übergeben werden. Den Einstiegspunkt für die Erzeugung der graphischen Oberfläche stellt in JavaFX hingegen die sofort anschießend ausgeführte Methode start() dar. Die beiden Konsolenausgaben illustrieren die Reihenfolge der Aufrufe.

Der Parameter vom Typ Stage repräsentiert das vom Betriebssystem bereitgestellte Hauptfenster, dem in einer Swing-Anwendung etwa ein JFrame entspräche. Entsprechend diesem wird auch die Stage-Instanz mit einem Titel versehen. Am Ende des Beispiels wird der Stage die Scene übergeben werden. Doch dazu unten mehr.
Danach werden ein Button und ein Label deklariert und mit ihren Aufschriften initialisiert. Beim mit einem Leerstring initialisierte Label wird der Satzspiegel auf Mittelsatz gesetzt. Pos stellt zu diesem Zweck eine Enumeration dar, die eine ganze Reihe geometrischer Werte zur horizontalen und vertikalen Positionierung speichert.

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class HelloJavaFXWorld extends Application {

    @Override
    public void start(Stage primaryStage) {
        System.out.println("start() called");
        primaryStage.setTitle("Hallo Welt!");
        Button butt = new Button();
        butt.setText("Klick mich");
        final Label label = new Label("");
        label.setAlignment(Pos.CENTER);
        label.setStyle("-fx-border-width:1px; -fx-border-color: black;");
        label.setMinSize(87, 20);
        butt.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                label.setText("Hallo Welt!");
            }
        });
        
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(5);
        grid.setVgap(5);
        grid.add(label, 0, 0);
        grid.add(butt, 0, 1);
        grid.setGridLinesVisible(false);

        Scene scene = new Scene(grid, 250, 150);
        primaryStage.setScene(scene);
        scene.getStylesheets().add
        (HelloJavaFXWorld.class.getResource("styles/HelloJavaFXWorld.css").toExternalForm());
        primaryStage.show();
    }

    public static void main(String[] args) {
        System.out.println("main() called");
        launch(args);
    }
}

Die folgende Zeile ist typisch für JavaFX-Anwendungen. In ihr wird ein Rand des Labels mittels Stylesheets konfiguriert. Auffällig ist, dass die angeführten CSS-Elemente bis auf das Präfix -fx- denjenigen entsprechen, die für eine gleichartige Funktion aus dem Bereich der Webgestaltung mit HTML bekannt sind. Dies ist zwar häufig der Fall, aber nicht in jedem Fall. Eine Referenz der in JavaFX verwendbaren CSS-Elemente findet sich im JavaFX CSS Reference Guide. Das Stylesheet wird durch die Methode setStyle() der Klasse Control gesetzt.
Höhe und Breite des Labels können (noch) nicht durch Stylesheets gesetzt werden. Die Methode setMinSize() übernimmt statt dessen diese Aufgabe.

Das Behandeln von Aktionen erfolgt etwas anders als in der von Java bekannten Weise. Seine detaillierte Darstellung muss einem zukünftigen Artikel vorbehalten bleiben. Nähere Informationen liefert hierzu jedoch die (englische) Dokumentation unter http://docs.oracle.com/javafx/2/events/jfxpub-events.htm. Buttons, bzw. deren Oberklasse ButtonBase besitzen eine Eigenschaft onAction, der durch die Methode setOnAction() ein EventHandler mitgeteilt wird. Das generische Interface wird auf einen speziellen Typ festgelegt (hier einem ActionEvent) und führt durch seine Methode handle() die Aktion aus, für den der EventHandler registriert ist.

JavaFX Hello-World-Fenster

Im folgenden Quelltextabschnitt erfolgt die Positionierung der Komponenten. Hierzu wird zunächst ein GridPane erzeugt, ein Bereich, auf dem Komponenten rasterartig angeordnet, im Gegensatz zu Javas GridLayout jedoch auch Spalten und Reihen bei Bedarf vereint werden können. Zudem besitzen die einzelnen Zellen nicht die gleiche Größe, sondern richten diese nach den Maßen des Inhalts. Mit den Methoden setHgap() und setVgap() können die horizontalen und vertikalen Abstände zwischen den Zellen definiert werden. Zur Kontrolle des Layouts kann während der Gestaltungsarbeit die Eigenschaft gridLinesVisible durch setGridLinesVisible(true) gesetzt werden.

Gegen Ende des Beispiels wird der Haupt-Container der Applikation erzeugt. Er ist vom Typ Scene und definiert durch seinen Konstruktor auch die Größe der Darstellung.
Der Aufbau einer JavaFX-Anwendung erfolgt baumartig in einem scene graph. Das Scene-Objekt stellt den obersten Knoten des Graphen dar und wird als root bezeichnet. Dem root-Objekt können weitere Knoten (Bilder, Media-Inhalte, Container, etc.) eingefügt werden (hier GridPane), die als Gruppenknoten (group nodes) wiederum Knoten enthalten können oder als Einzelknoten (leaves, plain nodes) existieren. Die Scene wird dem Hauptfenster übergeben bevor dies sichtbar gesetzt wird. Vorher jedoch wird die zweite Variante der Übergabe eines Stylesheet demonstriert, bei der das

@CHARSET "UTF-8";
.root {-fx-background-color:#ff0000;}
.label {
	-fx-text-fill:#ffffff;
	-fx-font-weight:bold;
}

.button {
	-fx-font:14px "Tahoma";
}

Label und der root-Container, das GridPane farblich eingestellt werden.