Table Item
The following class contains 2 properties a name (String
) and the size (double
). Both properties are wrapped in JavaFX properties to allow the TableView
to observe changes.
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
public Person(String name, double size) {
this.size = new SimpleDoubleProperty(this, "size", size);
this.name = new SimpleStringProperty(this, "name", name);
}
private final StringProperty name;
private final DoubleProperty size;
public final String getName() {
return this.name.get();
}
public final void setName(String value) {
this.name.set(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final double getSize() {
return this.size.get();
}
public final void setSize(double value) {
this.size.set(value);
}
public final DoubleProperty sizeProperty() {
return this.size;
}
}
Sample Application
This application shows a TableView
with 2 columns; one for the name and one for the size of a Person
. Selecting one of the Person
s adds the data to TextField
s below the TableView
and allow the user to edit the data. Note once the edit is commited, the TableView
is automatically updated.
To every for every TableColumn
added to the TableView
a cellValueFactory
is assigned. This factory is responsible for converting table items (Person
s) to ObservableValue
s that contain the value that should be displayed in the table cell and that allows the TableView
to listen to any changes for this value.
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class TableSample extends Application {
@Override
public void start(Stage primaryStage) {
// data for the tableview. modifying this list automatically updates the tableview
ObservableList<Person> data = FXCollections.observableArrayList(
new Person("John Doe", 1.75),
new Person("Mary Miller", 1.70),
new Person("Frank Smith", 1.80),
new Person("Charlotte Hoffman", 1.80)
);
TableView<Person> tableView = new TableView<>(data);
// table column for the name of the person
TableColumn<Person, String> nameColumn = new TableColumn<>("Name");
nameColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Person, String> param) {
return param.getValue().nameProperty();
}
});
// column for the size of the person
TableColumn<Person, Number> sizeColumn = new TableColumn<>("Size");
sizeColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person, Number>, ObservableValue<Number>>() {
@Override
public ObservableValue<Number> call(TableColumn.CellDataFeatures<Person, Number> param) {
return param.getValue().sizeProperty();
}
});
// add columns to tableview
tableView.getColumns().addAll(nameColumn, sizeColumn);
TextField name = new TextField();
TextField size = new TextField();
// convert input from textfield to double
TextFormatter<Double> sizeFormatter = new TextFormatter<Double>(new StringConverter<Double>() {
@Override
public String toString(Double object) {
return object == null ? "" : object.toString();
}
@Override
public Double fromString(String string) {
if (string == null || string.isEmpty()) {
return null;
} else {
try {
double val = Double.parseDouble(string);
return val < 0 ? null : val;
} catch (NumberFormatException ex) {
return null;
}
}
}
});
size.setTextFormatter(sizeFormatter);
Button commit = new Button("Change Item");
commit.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Person p = tableView.getSelectionModel().getSelectedItem();
p.setName(name.getText());
Double value = sizeFormatter.getValue();
p.setSize(value == null ? -1d : value);
}
});
// listen for changes in the selection to update the data in the textfields
tableView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Person>() {
@Override
public void changed(ObservableValue<? extends Person> observable, Person oldValue, Person newValue) {
commit.setDisable(newValue == null);
if (newValue != null) {
sizeFormatter.setValue(newValue.getSize());
name.setText(newValue.getName());
}
}
});
HBox editors = new HBox(5, new Label("Name:"), name, new Label("Size: "), size, commit);
VBox root = new VBox(10, tableView, editors);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}