Java FX Panes
Willemers Informatik-Ecke
Ein Pane ist ein Brett, auf dem Elemente angeordnet werden können. Die Scene von Haus aus nur ein Element auf. Dieses Element ist typischerweise ein Pane, auf dem weitere Panes für die Anordnung der Elemente sorgen.

HBox und VBox Stapelt die Elemente einzeln neben- bzw. übereinander
FlowPane Füllt Reihe auf und bricht bei Platzmangel um
BorderPane Randelemente mit großem Zentrum: Top, Bottom, Left und Right.
GridPane Im Raster angeordnet, typischerweise für Dialoge
StackPane Elemente werden an derselben Position aufeinander gelegt.
TilePane Ordnet die enthaltenen Elemente in gleichbleibend großem Layout.

Die Panes haben gemeinsame Methoden:

HBox und VBox

Mehrere Elemente werden nebeneinander (HBox) oder untereinander (VBox) angeordnet. Am Ende der Reihe wird nicht umgebrochen, es wird also nur eine Zeile in Anspruch genommen.

Sie können Elemente in die Boxen bringen, indem Sie zunächst über die Methode \funktion{getChildren()} ermitteln. Dieser Liste fügen Sie über die Methode \funktion{add()} ein neues Element hinzu. Mit der Methode \funktion{addAll()} können mehrere Elemente gleichzeitig eingefügt werden, die dazu kommasepariert als Parameter übergeben werden.

@Override
public void start(Stage hauptStage) throws Exception {
    HBox pane = new HBox();
    String str = "";
    for (int i = 0; i < 5; i++) {
        str += i;
        Button b = new Button(str);
        pane.getChildren().add(b);
    }
    Scene scene = new Scene(pane, 400, 300);
    hauptStage.setScene(scene);
    hauptStage.show();
}
Im Parameter des Konstruktors kann der Abstand zwischen den enthaltenen Elementen in Pixeln vorgegeben werden.

FlowPane

Im FlowPane werden die enthaltenen Elemente solange nebeneinander angeordnet, bis der Rand zu einem Umbruch zwingt. Ein FlowPane kann horizontal oder vertikal als Geschmacksrichtung annehmen. Die Richtung bestimmt der erste Parameter des Konstruktors (Orientation.HORIZONTAL oder Orientation.VERTICAL).
FlowPane root = new FlowPane(Orientation.HORIZONTAL, 5, 3);
Der erste Parameter gibt an, dass zunächst alle Elemente horizontal positioniert werden. Im Beispiel werden die Elemente nebeneinander um 5 Pixel und untereinander um 3 Pixel voeneinander getrennt.

GridPane

Zu einem Grid werden Elemente mit der Methode add() hinzugefügt. Der erste Parameter ist das Element oder ein anderes Pane. Die nächsten zwei Werte geben X- und Y-Position des Rasterfeldes an. add(button, 2, 1) würde also button im dritten Feld waagerecht und im zweiten Feld senkrecht einsetzen.

Optional können zwei weitere Zahlen als Parameter übergeben werden. Sie geben an, wieviele Rasterfelder das Element in X- bzw. Y-Richtung belegt.

@Override
public void start(Stage hauptStage) throws Exception {
    GridPane pane = new GridPane();
    TextField editName = new TextField();
    TextField editStr = new TextField();
    TextField editOrt = new TextField();
    pane.add(new Label("Ihre Anschrift"), 0, 0, 2, 1);
    pane.add(new Label("Name:"), 0, 1);
    pane.add(editName, 1, 1);
    pane.add(new Label("Straße:"), 0, 2);
    pane.add(editStr, 1, 2);
    pane.add(new Label("Ort:"), 0, 3);
    pane.add(editOrt, 1, 3);
    Scene scene = new Scene(pane, 400, 300);
    hauptStage.setScene(scene);
    hauptStage.show();
}
Die Methoden setHgap() und setVgap() schaffen einen Abstand zwischen die horizonalen bzw. vertikalen Felder. Der Parameter wird in Pixeln angegeben.

Ansonsten fügen die Pane Kontrollelemente oder andere Panes durch den Aufruf von pane.getChildren().add(control) hinzu.

BorderPane

Das BorderPane ordnet um ein mittiges Element die Randbereiche, die als Top, Bottom, Left und Right bezeichnet werden. Vergrößerungen des Panes schlagen direkt auf das zentrale Element durch.

BorderPane besitzt die Methoden setCenter(), setLeft(), setRight(), setBottom() und setTop() für die Positionierung von Elementen. Die Methoden erwarten als Parameter das Element oder ein Pane mit Elementen.

Die zentrale Element wird bei Vergrößerung gedehnt. Die Seitenelemente nehmen nur die Breite ein, die dort angelegte Elemente benötigen. Top und Button nehmen nur die Höhe ein, die dort angelegte Elemente anfordern.

Die Elemente werden linksbündig in ihren Bereichen ausgerichtet. Nur im zentralen Bereich wird das Element horizontal wie vertikal zentriert. Mit der statischen Methode BorderPane.setAlignment() können Elemente innerhalb ihres Bereichs ausgerichtet werden.

BorderPane border = new BorderPane();
border.setTop(top);
BorderPane.setAlignment(top, Pos.CENTER);
border.setLeft(new Label("left"));
border.setRight(new Label("right"));
border.setCenter(new Label("center"));
border.setBottom(new Label("bottom"));

Beispiel für die Kombination verschiedener Panes

Das folgende Programm verwendet ein Borderlayout als Grund-Layout. In das Center wird ein Grid-Layout für eine Adresseingabe gelegt. In den Bottom-Bereich werden mit einem Flow-Layout zwei Buttons gestellt.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class LayoutFx extends Application {

    public static void main(String[] args) {
        launch(args); // sorgt indirekt für den Aufruf von start
    }

    TextField nameEdit = new TextField();
    TextField strasseEdit = new TextField();
    TextField ortEdit = new TextField();

    @Override
    public void start(Stage hauptStage) {
        // hauptStage.setTitle("Erster Versuch in JavaFX");
        Button okBtn = new Button("Ok");
        okBtn.setPrefSize(100, 0); // Höhe selbst bestimmen!
        Button cancelBtn = new Button("Abbruch");
        cancelBtn.setPrefSize(100, 0);
        FlowPane flow = new FlowPane();
        flow.getChildren().add(okBtn);
        flow.getChildren().add(cancelBtn);
        // Baue ein Grid für das Raster für die Adresseingabe
        GridPane grid = new GridPane();
        grid.add(new Label("Name:"), 0, 0);
        grid.add(nameEdit, 1, 0);
        grid.add(new Label("Straße:"), 0, 1);
        grid.add(strasseEdit, 1, 1);
        grid.add(new Label("PLZ Ort:"), 0, 2);
        grid.add(ortEdit, 1, 2);
        // BorderPane nimmt den Anwendungsrahmen auf
        BorderPane border = new BorderPane(); // Layout-Container
        border.setCenter(grid);
        border.setBottom(flow);
        Scene scene = new Scene(border); // scene beschreibt den Inhalt
        hauptStage.setScene(scene);
        hauptStage.show(); // fehlt das, sieht man gar nichts
    }
}