TableView
Das TableView dient zur Darstellung und Editierung von Daten in tabellarischer
Form. Auch wenn möglich, sollte das TableView nicht zum Layout von Komponenten
als Container missbraucht werden. Hier sollte lieber auf das GridPane oder andere
Layout - Komponenten zurückgegriffen werden.
Das TableView ist Verwandt mit dem ListView und gehört zu den etwas
komplexeren Komponenten. Bevor das TableView eingesetzt werden kann, sollte man
sich etwas Zeit für die Einarbeitung lassen.
Um der Thematik TableView näher zu kommen, wollen wir als erstes Beispiel
eine sehr einfache Tabelle erzeugen, die uns in den Zellen ein paar Texte ausgibt.
Die nachfolgende Grafik zeigt, was wir als Ergebnis unserer Programmierung erhalten werden.
Bevor wir uns der TableView-Programmierung hingeben programmieren wir die Klasse
ValueClass (Name ist willkürlich). Diese Klasse stellt später die Daten
für die Darstellung im TableView zur Verfügung.
public class ValueClass {
private String column1;
private String column2;
private String column3;
public ValueClass(String column1, String column2, String column3) {
this.column1 = column1;
this.column2 = column2;
this.column3 = column3;
}
public String getColumn1() {
return column1;
}
public String getColumn2() {
return column2;
}
public String getColumn3() {
return column3;
}
}
Nachdem wir die Datenklasse programmiert haben, wenden wir uns der Programmierung
der Darstellung des TableView zu.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
public class MyTableView extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("MyTableView");
stage.setWidth(450);
stage.setHeight(500);
TableView tableView = createTableView();
((Group) scene.getRoot()).getChildren().addAll(tableView);
stage.setScene(scene);
stage.show();
}
private TableView createTableView() {
// Darzustellende Daten
ObservableList<ValueClass> data = FXCollections.observableArrayList(
new ValueClass("R0 C0", "R0 C1", "R0 C2"),
new ValueClass("R1 C0", "R1 C1", "R1 C2"),
new ValueClass("R2 C0", "R2 C1", "R2 C2"),
new ValueClass("R3 C0", "R3 C1", "R3 C2"),
new ValueClass("R4 C0", "R4 C1", "R4 C2")
);
// Spaltendefinition
TableColumn<ValueClass, String> col1 = new TableColumn<ValueClass, String>("Col 1");
col1.setCellValueFactory(new PropertyValueFactory<ValueClass, String>("column1"));
TableColumn<ValueClass, String> col2 = new TableColumn<ValueClass, String>("Col 2");
col2.setCellValueFactory(new PropertyValueFactory<ValueClass, String>("column2"));
TableColumn<ValueClass, String> col3 = new TableColumn<ValueClass, String>("Col 3");
col3.setCellValueFactory(new PropertyValueFactory<ValueClass, String>("column3"));
// Tabellenerzeugung
TableView<ValueClass> tableView = new TableView<ValueClass>();
tableView.setItems(data);
tableView.getColumns().add(col1);
tableView.getColumns().add(col2);
tableView.getColumns().add(col3);
return tableView;
}
}
Die Methode start definiert allgemein das JavaFX View und ist unabhängig vom
TableView. Das darzustellende TableView programmieren wir in der Methode
createTableView. Als Erstes definieren wir mit data ein
FXCollections.observableArrayList, welches die darzustellenden Daten enthält.
Im Anschluss definieren wir drei Spalten, die wir dem TableView zuweisen.
Abschließend geben wir das TableView als Ergebnis der Methode zurück.
Im aktuellen Stand unseres TableView werden die Daten wie gewollt dargestellt.
Was aber etwas unangenehm auffällt, ist dass unsere Tabelle eine zusätzliche, leere Spalte
und zusätzliche, leere Zeilen zeichnet. Im Nachfolgendem wollen wir unser Programm derart
modifizieren, sodass keine zusätzliche Spalte und keine zusätzliche Zeilen gezeichnet werden.
Um das zusätzliche Zeichnen der letzten Spalte zu vermeiden, setzen wir das Feld
columnResizePolicy der TableView von TableViewUNCONSTRAINED_RESIZE_POLICY
auf TableView.CONSTRAINED_RESIZE_POLICY.
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Um das Zeichnen der zusätzlichen Zeilen zu verhindern, ist ein wenig mehr Aufwand notwendig.
Hier definieren wir zwei Callback Objekte, welche das Zeichnen der Zeilen und
der einzelnen Zellen behandeln. Das nachfolgende Beispiel zeigt die Implementierung der
beiden Callback Objekte für unser Beispiel.
Callback<TableColumn<ValueClass,String>, TableCell<ValueClass,String>> myCallback
= new Callback<TableColumn<ValueClass,String>, TableCell<ValueClass,String>>() {
@Override public TableCell call(TableColumn param) {
return new TableCell() {
@Override protected void updateItem(Object item, boolean empty) {
if (empty) super.setVisible(false);
else super.setText(item.toString());
}
};
}
};
col1.setCellFactory(myCallback);
col2.setCellFactory(myCallback);
col3.setCellFactory(myCallback);
Callback<TableView<ValueClass>,TableRow<ValueClass>> myCallback2 =
new Callback<TableView<ValueClass>,TableRow<ValueClass>>() {
@Override public TableRow call(TableView table) {
return new TableRow<ValueClass>() {
protected void updateItem(ValueClass item, boolean empty) {
if (empty) super.setStyle("-fx-background-color: lightyellow");
super.updateItem(item,empty);
}
};
}
};
tableView.setRowFactory(myCallback2);
return tableView;
}
Nachfolgend der vollständige Quelltext unserer Tabelle zur einfachen Darstellung von Daten.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.*;
public class MyTableView4 extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("MyTableView");
stage.setWidth(450);
stage.setHeight(500);
TableView tableView = createTableView();
((Group) scene.getRoot()).getChildren().addAll(tableView);
stage.setScene(scene);
stage.show();
}
private TableView createTableView() {
// Darzustellende Daten
ObservableList<ValueClass> data = FXCollections.observableArrayList(
new ValueClass("R0 C0", "R0 C1", "R0 C2"),
new ValueClass("R1 C0", "R1 C1", "R1 C2"),
new ValueClass("R2 C0", "R2 C1", "R2 C2"),
new ValueClass("R3 C0", "R3 C1", "R3 C2"),
new ValueClass("R4 C0", "R4 C1", "R4 C2")
);
// Spaltendefinition
TableColumn<ValueClass, String> col1 = new TableColumn<ValueClass, String>("Col 1");
col1.setCellValueFactory(new PropertyValueFactory<ValueClass, String>("column1"));
TableColumn<ValueClass, String> col2 = new TableColumn<ValueClass, String>("Col 2");
col2.setCellValueFactory(new PropertyValueFactory<ValueClass, String>("column2"));
TableColumn<ValueClass, String> col3 = new TableColumn<ValueClass, String>("Col 3");
col3.setCellValueFactory(new PropertyValueFactory<ValueClass, String>("column3"));
// Tabellenerzeugung
TableView<ValueClass> tableView = new TableView<ValueClass>();
tableView.setItems(data);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tableView.getColumns().add(col1);
tableView.getColumns().add(col2);
tableView.getColumns().add(col3);
Callback<TableColumn<ValueClass,String>, TableCell<ValueClass,String>> myCallback
= new Callback<TableColumn<ValueClass,String>, TableCell<ValueClass,String>>() {
@Override public TableCell call(TableColumn param) {
return new TableCell() {
@Override protected void updateItem(Object item, boolean empty) {
if (empty) super.setVisible(false);
else super.setText(item.toString());
}
};
}
};
col1.setCellFactory(myCallback);
col2.setCellFactory(myCallback);
col3.setCellFactory(myCallback);
Callback<TableView<ValueClass>,TableRow<ValueClass>> myCallback2 =
new Callback<TableView<ValueClass>,TableRow<ValueClass>>() {
@Override public TableRow call(TableView table) {
return new TableRow<ValueClass>() {
protected void updateItem(ValueClass item, boolean empty) {
if (empty) super.setStyle("-fx-background-color: lightyellow");
super.updateItem(item,empty);
}
};
}
};
tableView.setRowFactory(myCallback2);
return tableView;
}
}
Die Ausführung des Programms führt zur Anzeige folgenden Fensters:
http://docs.oracle.com/ 
12 Table View
http://docs.oracle.com/javafx/2/ui_controls/table-view.htm
Jonathan Giles - Tech Lead, JavaFX UI Controls
Hacking TableView
http://www.youtube.com/watch?v=udc2iRZBF0M
http://docs.oracle.com/ 
JavaFX 2 - TableView - API Dokumentation