12.3JavaFX-Komponenten und Layout-Container-Klassen
JavaFX kommt wie Swing mit einem Satz von Standardkomponenten im Paket javafx.scene.control und hat Control als Basisklasse.
12.3.1Überblick über die Komponenten
Die Klassennamen sind selbsterklärend:
Label
Hyperlink
Button
RadioButton
ToggleButton
CheckBox
ChoiceBox
TextField
PasswordField
ListView
TableView
TitledPane
ScrollPane
ProgressBar
ProgressIndicator
Pane mit Unterklassen für unterschiedliche Layouts
Styling
Cascading Style Sheets (CSS) können das Aussehen anpassen. Der Vorteil ist, dass dies deklarativ ohne Programmieraufwand möglich ist. Die CSS-Deklaration lässt sich in eine Datei auslagern und für eine ganze JavaFX-Applikation anwenden oder auch lokal mit setStyle() setzen. Neben dem Styling lässt sich eine komplett neue Skin definieren, etwa für Oberflächen mit besonders starken Kontrasten.
Bei der Konfiguration findet sich keine Klasse vom AWT oder von Swing wieder. Im eingehenden Beispiel ließ sich das schon an der JavaFX-eigenen Klasse Font ablesen. Das geht weiter bei den Icons, die als ImageView-Objekte zum Beispiel an Schaltflächen gesetzt werden. Für Farben gibt es die eigene Color-Klasse mit reichlich vorgefertigten Farbkonstanten und einer Methode Color.web(), die die Farbangaben hexadezimal webüblich annimmt. JavaFX ist als vollständig neue Technologie zu verstehen, die alte Zöpfe abschneidet.
12.3.2Listener/Handler zur Ereignisbeobachtung
Die Ereignisbehandlung folgt dem bekannten Listener-Prinzip. Es ist unnötig, zu betonen, dass neue JavaFX-Typen verwendet werden. Einen anderen Unterschied gibt es, der an GWT erinnert: Jede Komponente ist ein Knoten, und jedem Knoten lässt sich im Prinzip jeder Listener zuordnen, wobei der Listener bei JavaFX Handler genannt wird.
Allgemeiner Event-Handler
Die Klasse für alle Knoten Node deklariert:
addEventHandler(EventType<T>, EventHandler<? super T>) zum Hinzufügen der Handler
removeEventHandler(EventType<T>, EventHandler<? super T>) zum Abmelden der Handler
addEventHandler() ist also eine allgemeine Möglichkeit, etwa einer Schaltfläche einen Horcher zuzuordnen. Für einen Button b könnte das so aussehen:
@Override public void handle( ActionEvent e ) {
…
}
} );
Spezielle Handler
Neben der Möglichkeit, über die addEventHandler()-Methode einen Handler hinzuzufügen, bieten die Komponentenklassen auch eigene Hinzufügemethoden, etwa der Button die Methode setOnAction(EventHandler<ActionEvent>).
Das nächste Beispiel deaktiviert beim Klick auf die Schaltfläche diese:
Listing 12.2com/tutego/insel/javafx/ButtonSetOnActionDemo.java, start()
public void start( Stage stage ) {
final Button b = new Button( "OK" );
b.setFont( Font.font( "Calibri", 30 ) );
Image image = new Image( getClass().getResourceAsStream( "/images/ok.png" ) );
b.setGraphic( new ImageView( image ) );
b.setOnAction( new EventHandler<ActionEvent>() {
@Override public void handle( ActionEvent e ) {
b.setDisable( true );
}
} );
stage.setScene( new Scene( b ) );
stage.show();
}
12.3.3Panels mit speziellen Layouts
Unser Beispiel nutzt zur Positionierung absolute Angaben mit setX() und setY(). Das ist für Komponenten eher unüblich, und eine Anordnung nach speziellen Layouts ist zu bevorzugen. JavaFX bietet spezielle Container-Klassen, die jeweils ein individuelles Layout realisieren.
Vergleich zwischen Swing und JavaFX
Das ist anders als bei Swing, bei dem das Strategiemuster zum Zuge kommt: Ein Container ist mit einem Layoutmanager assoziiert, der die Kinder anordnet.
JavaFX-Container
Es stehen in JavaFX folgende Container-Klassen zur Verfügung (in Klammern stehen die vergleichbaren Layoutmanager in Swing, die etwa einem JPanel zugewiesen werden):
BorderPane (vergleichbar mit BorderLayout)
FlowPane (vergleichbar mit FlowLayout)
HBox, VBox (vergleichbar dem Container über Box.createHorizontalBox() bzw. Box.createVerticalBox())
StackPane (vergleichbar mit CardLayout)
GridPane (wie ein einfacheres GridBagLayout)
TilePane (vergleichbar mit GridLayout)
AnchorPane (vergleichbar mit BorderLayout und Komponenten in allen Ecken)
Beispiel
Im nächsten Beispiel soll ein kleines Formular Vor- und Nachname erfassen. Die GridPane ist für Anordnungen in einem Raster bestens geeignet.
Listing 12.3com/tutego/insel/javafx/GridPaneDemo.java, start()
public void start( Stage stage ) {
GridPane grid = new GridPane();
grid.setHgap( 10 );
grid.setVgap( 10 );
grid.setPadding( new Insets( 10, 10, 10, 10 ) );
Label header = new Label( "Kontaktdaten" );
header.setFont( new Font( 20 ) );
GridPane.setHalignment( header, HPos.CENTER );
grid.add( header,
0 /*x*/, 0 /*y*/,
2 /*colSpan*/, 1 /*rowSpan*/ );
grid.add( new Label( "Vorname" ), 0, 1 );
grid.add( new TextField(), 1, 1 );
grid.add( new Label( "Nachname" ), 0, 2 );
grid.add( new TextField(), 1, 2 );
stage.setScene( new Scene( grid ) );
stage.show();
}
Abbildung 12.2Screenshot der Anwendung GridPaneDemo
Die GridPane wächst automatisch und muss nicht mit einer festen Anzahl von Spalten/Zeilen erzeugt werden. Die add(…)-Methode setzt später eine Komponente an die gewünschte Stelle, wobei es eine überladene add(…)-Methode gibt, die die Komponente über mehrere Zellen verteilen kann. Wie die Komponente dann in ihrem Bereich ausgerichtet wird, bestimmen die statischen Methoden setHalignment(…) und setValignment(…), denen die auszurichtende Komponente und die Orientierung mitgegeben wird.