Java FXML

Willemers Informatik-Ecke

Das einzig seriöse Javabuch :-) Mehr...


Bei Amazon bestellen

Ferien an der Flensburger Förde
Falls ich Ihnen helfen konnte:!
Vielen Dank!!!
2017-04-06
Statt die Oberfläche klassisch in einem Programm zusammenzubauen, können Sie diese auch mit dem XML-Dialekt FXML beschreiben und dann per Annotationen nutzen.

Eine FXML-Datei erzeugen

Sie klicken das Projekt mit der rechten Maustaste an und wählen aus dem Kontextmenü File|New|Other. Im Dialog wählen Sie JavaFX und darunter New FXML Document aus. Es entsteht der Rahmen einer FXML-Datei.
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>

<AnchorPane xmlns:fx="http://javafx.com/fxml/1">
    <!-- TODO Add Nodes -->
</AnchorPane>
Daraus können Sie nun Ihren Dialog erzeugen. Dazu benötigen Sie gute FXML-Kenntnisse oder den SceneBuilder. Für Java FX stellt Oracle den SceneBuilder zur Verfügung, mit denen FXML-Dateien so bearbeitet werden können, dass man per Mausklick Panes und Kontrollelemente zur Fensteroberflächen zusammenklicken kann.

Der SceneBuilder wird von Oracle ledigliche als Source zur Verfügung gestellt. Die Website http://gluonhq.com/products/scene-builder bietet auch ein Installationspaket für alle gängigen Plattformen.

Integration des SceneBuilders in Eclipse

Die Verwendung des SceneBuilders setzt natürlich die Einbindung von JavaFX in Eclipse voraus. Dazu installieren Sie das Paket e(fx)clipse aus dem Eclipse Marketplace im Menü Help.

Damit Eclipse weiß, wo es den SceneBuilder findet, klicken Sie zunächst in das Menü Window|Preferences. Im darauf erscheinenden Dialog klicken Sie in der linken Spalte den Punkt JavaFX an. Auf der rechten Seite können Sie nun das SceneBuilder executable über den Button Browse auswählen.

Wenn Sie nach diesen Vorbereitungen die Datei FXML-Datei im Projekt mit der rechten Maustaste anklicken, können Sie den Punkt Open with SceneBuilder anklicken und der SceneBuilder erscheint.

Er übernimmt die FXML-Datei aus dem Eclipse-Projekt und stellt sie grafisch dar. Da sie bislang fast leer ist, gibt es allerdings nicht viel zu sehen.

In der linken Spalte zeigt der SceneBuilder Ressourcen wie Container oder Kontrollelemente, aus denen Sie durch Mausziehen auswählen und im Mittelfeld Ihr Fenster zusammenklicken können.

In der rechten Spalte erscheint die jeweils angewählte Ressource. Sie können dort deren Attribute einstellen.

Nach dem Sichern und Verlassen des SceneBuilders sieht Ihre FXML-Datei deutlich anders aus. Das Beispiel habe ich ein wenig zurechtgestutzt.

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<AnchorPane xmlns:fx="http://javafx.com/fxml/1"
          xmlns="http://javafx.com/javafx/8.0.111"
   fx:controller="application.SpielerController">
   <children>
      <GridPane layoutX="-88.0" layoutY="-106.0">
        <columnConstraints>
          <ColumnConstraints hgrow="SOMETIMES" prefWidth="100.0" />
          <ColumnConstraints hgrow="SOMETIMES" prefWidth="100.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Button text="OK" GridPane.columnIndex="1"
                 GridPane.rowIndex="2"
                 fx:id="btOk" onAction="#klickOk"/>
            <Label text="Spieler" />
            <Label text="Punkte" GridPane.rowIndex="1" />
            <TextField fx:id="tfSpieler" GridPane.columnIndex="1" />
            <TextField fx:id="tfPunkte" GridPane.columnIndex="1"
                 GridPane.rowIndex="1" />
         </children>
      </GridPane>
   </children>
</AnchorPane>
Hinzugefügt wurden fx:controller, fx:id und onAction. Der Zweck wird gleich klar.

Einbinden der FXML-Datei in Java

Um das Hauptprogramm zu erzeugen, klicken Sie mit der rechten Maustaste auf das Projekt, dann New|Other. Unter JavaFX findet sich noch ein Unterpunkt Classes. Darin gibt es einen Punkt JavaFX Main Class. Diese möchte einen Namen haben. Main wäre nicht schlecht.
package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Parent p = FXMLLoader.load(getClass().getResource(
                    "/FxMaske.fxml"));
            Scene scene = new Scene(p);
            scene.getStylesheets().add(getClass().getResource(
                    "application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Zum Controller

Nun sollte das Fenster korrekt dargestellt werden, verhält sich aber ausgesprochen passiv. Man wünscht sich ein paar Aktivitäten. Beispielsweise könnte eine Methode aufgerufen werden, wenn auf den Button geklickt wird. Diese könnte dann die Eingabefelder auslesen.

Dazu müssen in der FXML-Datei ein paar Kleinigkeiten eingetragen werden. Im äußeren Pane wird hinterlegt, wie die Klasse heißt, die das Fenster steuert, also der Controller.

fx:controller="application.SpielerController"
Die Elemente müssen mit Variablennamen im Java-Programm in Verbindung gebracht werden. Dazu dienen fx:id-Einträge. Der Button hat zusätzlich mit onAction die Möglichkeit auf die Eventmethode zu verweisen.
<Button text="OK" GridPane.columnIndex="1" GridPane.rowIndex="2"
    fx:id="btOk" onAction="#klickOk"/>
<TextField fx:id="tfSpieler" GridPane.columnIndex="1"...
<TextField fx:id="tfPunkte" GridPane.columnIndex="1" ...
Alles verweist auf die Controller-Klasse. Hier wird über die Annotation @FXML ein Verweis auf die Elemente in der FXML-Datei bezogen.
package application;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;

public class SpielerController implements Initializable {

    @FXML
    private TextField tfSpieler;

    @FXML
    private TextField tfPunkte;

    private SpielerModel model;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        model = new SpielerModel();
    }

    public void klickOk() {
        model.setName(tfSpieler.getText());
    }
}

Das Modell

Die eigentlichen Daten ermittelt die Controller-Klasse aus der Modell-Klasse. Sie heißt hier SpielerModel.
package application;

public class SpielerModel {
    private String spieler = "";
    private int punkte = 0;

    public void setName(String name) {
        System.out.println("Name="+name);
        this.spieler = name;
    }

}


Homepage - Java - Java FX (C) Copyright 2017 Arnold Willemer