Overview
Die TableView ermöglicht es dir, Objektdaten in Form einer Tabelle in deiner JavaFX-Anwendung darzustellen. Die TableView gehört zu den eher komplexeren JavaFX-Nodes - doch keine Sorge: Am Ende des Tutorials gehört Sie dir!
// Schnelles Code-Beispiel
TableView<Produkt> tabelle = new TableView<>();
TableColumn<TypTabelle, TypSpalte> columnX = new TableColumn<>("Spaltenname");
columnX.setCellValueFactory(new PropertyValueFactory<>("instanzvariable"));
tabelle.getColumns().addAll(columnX);
tabelle.setItems(getListe());
Eine TableView macht es dir möglich, eine Tabellen-Ansicht mit Objektdaten darzustellen. Repräsentiert ist die TableView in der JavaFX-Klasse javafx.scene.control.TableView. Wie bei der ListView steht hinter der TableView eine ObservableList, welche die einzelnen Elemente verwaltet (dazu weiter unten mehr).
Hier ein Beispiel, wie das dann in einer JavaFX-Anwendung aussehen kann:
In diesem Ausschnitt werden verschiedene Eigenschaften von drei Objekten des Typs Produkt in Tabellenform angezeigt.
Die TableView ist eine generische Klasse, das heißt, dass wir bei der Erstellen einen Typ-Parameter in spitzen Klammern angeben müssen. Dieser Typ-Parameter bestimmt, welche Objekt-Typen die Tabelle aufnehmen soll.
Wenn wir zum Beispiel wie im Screenshot oben Daten von Objekten des Typs Produkt in der Tabelle angezeigt haben wollen, dann sieht die Erzeugung eines TableView-Objekts so aus:
TableView<Produkt> tabelle = new TableView<>();
Wie gesagt sind es die Daten (genauer gesagt: Werte der Instanzvariablen) von Produkt-Objekten, die in die Tabelle kommen. Die Implementierung der Klasse Produkt ist deshalb sehr relevant und es müssen vor allem die Getter-Methoden nach der konventionellen Schreibweise gesetzt sein, damit die Objektdaten in die Tabelle übertragen werden können:
public class Produkt {
int nummer;
String name;
double preis;
public Produkt(int nummer, String name, double preis) {
this.nummer = nummer;
this.name = name;
this.preis = preis;
}
public int getNummer() {
return nummer;
}
public String getName() {
return name;
}
public double getPreis() {
return preis;
}
// Setter hier aus Platzgründen ausgelassen
}
Mit dem Erzeugen eines TableView-Objekts ist es noch nicht getan. Die Tabelle muss im nächsten Schritt nämlich noch mit den einzelnen Spalten strukturell aufgebaut werden.
Eine Spalte wird durch die Klasse TableColumn repräsentiert. TableColumn ist gleich doppelt generisch und verlangt bei der Initialisierung zusätzlich noch ein String-Argument. Hier ein allgemeines Beispiel:
Willkommen beim Parameter-Overlord 😅! Jetzt etwas genauer:
Konkret sieht das für unseren Spalten der Tabelle so aus:
TableColumn<Produkt, Integer> nummer_column = new TableColumn<>("Nummer");
TableColumn<Produkt, String> name_column = new TableColumn<>("Name");
TableColumn<Produkt, Double> preis_column = new TableColumn<>("Preis");
Jetzt müssen wir noch dafür sorgen, dass die Werte der Instanzvariablen der Produkt-Objekte auch tatsächlich in den Zellen der entsprechenden Spalte landen.
Hierzu rufen wir auf der TableColumn-Referenz die Methode setCellValueFactory() auf und setzen als Argument ein neues PropertyValueFactory-Objekt ein.
Das PropertyValueFactory-Objekt stellt die direkte Verbindung zur Instanzvariable des Produkt-Objekts her und liest deren aktuellen Wert aus:
nummer_column.setCellValueFactory(new PropertyValueFactory<>("nummer"));
name_column.setCellValueFactory(new PropertyValueFactory<>("name"));
preis_column.setCellValueFactory(new PropertyValueFactory<>("preis"));
Damit das auch funktioniert, müssen wir auf zwei Dinge achten:
Schließlich müssen die einzelnen Spalten noch der TableView hinzugefügt werden. Das läuft über den verketteten Methodenaufruf getColumns().addAll():
tabelle.getColumns().addAll(nummer_column, name_column, preis_column);
Unsere TableView ist nun fertig strukturiert und sieht so aus:
Unsere Tabelle ist jetzt noch leer und was jetzt noch fehlt, sind die Daten aus den Produkt-Objekten.
Hierzu muss man wissen, dass die einzelnen Elemente nicht in der TableView selbst gespeichert werden. Stattdessen ist in der TableView eine ObservableList verbaut, die für die eigentliche Verwaltung der einzelnen Elemente zuständig ist.
Wie gehen wir also vor?
Zunächst schreiben wir eine Methode, welche eine mit Produkt-Objekten gefüllte ObservableList zurückliefert:
public ObservableList<Produkt> getProdukte(){
ObservableList<Produkt> liste = FXCollections.observableArrayList();
liste.add(new Produkt(1, "Tablet", 500));
liste.add(new Produkt(2, "Notebook", 1000));
liste.add(new Produkt(3, "Smartphone", 900));
return liste;
}
Schließlich verbauen wir die die ObservableList in der Tabelle, indem wir auf der TableView-Referenz die Methode setItems() aufrufen:
tabelle.setItems(getProdukte());
Schon sind wir fertig:
<img alt="JavaFX tableView erstelen" style="width: 100%; max-width: 500px; margin-bottom: 20px" src="https://falconbyte.net/screens/tableview.jpg">
Für alle mit wenig Zeit - hier der vollständige Code:
package p1;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage){
TableView<Produkt> tabelle = new TableView<>();
// Nummer-Spalte
TableColumn<Produkt, Integer> nummer_column
= new TableColumn<>("Nummer");
nummer_column.setCellValueFactory(new PropertyValueFactory<>("nummer"));
nummer_column.setMinWidth(200);
// Name-Spalte
TableColumn<Produkt, String> name_column = new TableColumn<>("Name");
name_column.setCellValueFactory(new PropertyValueFactory<>("name"));
name_column.setMinWidth(200);
// Preis-Spalte
TableColumn<Produkt, Double> preis_column = new TableColumn<>("Preis");
preis_column.setCellValueFactory(new PropertyValueFactory<>("preis"));
preis_column.setMinWidth(200);
//Spalten in Tabelle packen:
tabelle.getColumns().addAll(nummer_column, name_column, preis_column);
//Daten in die Tabelle laden:
tabelle.setItems(getProdukte());
HBox box = new HBox();
box.getChildren().add(tabelle);
primaryStage.setScene(new Scene(box, 640, 480));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public ObservableList<Produkt> getProdukte(){
ObservableList<Produkt> liste = FXCollections.observableArrayList();
liste.add(new Produkt(1, "Tablet", 500));
liste.add(new Produkt(2, "Notebook", 1000));
liste.add(new Produkt(3, "Smartphone", 900));
return liste;
}
}
Java Basics
[Java einrichten] [Variablen] [Primitive Datentypen] [Operatoren] [if else] [switch-case] [Arrays] [Schleifen]
Objektorientierung
[Einstieg] [Variablen ] [Konstruktor] [Methoden] [Rekursion] [Statische Member] [Initializer] [Pass-by-value] [Objektsammlungen] [Objektinteraktion] [Objekte löschen]
Klassenbibliothek
[Allgemeines] [String ] [Math] [Wrapper] [Scanner] [java.util.Arrays] [Date-Time-API]
Vererbung
[Einstieg Vererbung] [Konstruktoren bei Vererbung ] [Der protected Zugriffsmodifikator] [Abstrakte Klassen und Methoden] [Polymorphie in Java] [Typumwandlung] [Die Klasse Object] [Die toString()-Methode] [Objekte vergleichen] [Was ist ein Interface?]