Cell Value Factory
For each column in your table, you set/create a Cell Value Factory. Each row has a corresponding object in tableview.getItems()
. To determine how this object is displayed across the columns, each column uses its own Cell Value Factory. The factories take in the object and return the value to be displayed.
Since String[][]
is an array of String[]
's, we want the factories to take in a String[]
and return the String
corresponding to its column.
Example
Here is an example of creating the Cell Value Factories in this way. It is a little verbose but that can be cleaned up with lambdas! (see Lambdas section).
// ---------------------------------------Initialize the data
String[][] data = ...; // Get name/value pairs from somewhere
// ---------------------------------------Setup a TableView with two TableColumns
/* ... Code ... */
// ---------------------------------------Add Cell Value Factories
nameColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<String[], String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<String[], String> p) {
String[] x = p.getValue();
if (x != null && x.length>0) {
return new SimpleStringProperty(x[0]);
} else {
return new SimpleStringProperty("<no name>");
}
}
});
valueColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<String[], String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<String[], String> p) {
String[] x = p.getValue();
if (x != null && x.length>1) {
return new SimpleStringProperty(x[1]);
} else {
return new SimpleStringProperty("<no value>");
}
}
});
// ---------------------------------------Add Data to TableView
tableView.getItems().addAll(Arrays.asList(data));
Result
If you throw this example (via the Source Code), on a Stage, this is what you get.

Lambdas
Java is a little verbose, especially when playing with anonymous classes. Thankfully there are lambdas, which bring a little readability back to Java. Here are the same Cell Value Factories from the example, re-written with lambdas.
nameColumn.setCellValueFactory((p)->{
String[] x = p.getValue();
return new SimpleStringProperty(x != null && x.length>0 ? x[0] : "<no name>");
});
valueColumn.setCellValueFactory((p)->{
String[] x = p.getValue();
return new SimpleStringProperty(x != null && x.length>1 ? x[1] : "<no value>");
});
Source Code
Here is a stand-alone JavaFX class that uses Cell Value Factories in this way.
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author nonfrt
*/
public class TableStuff extends Application {
@Override
public void start(Stage primaryStage) {
// Create the data structure
String[][] data = new String[5][2];
data[0] = new String[]{"Jon Skeet","876k"};
data[1] = new String[]{"Darin Dimitrov","670k"};
data[2] = new String[]{"BalusC","660k"};
data[3] = new String[]{"Hans Passant","635k"};
data[4] = new String[]{"Marc Gravell","610k"};
// Create the table and columns
TableView<String[]> tv = new TableView();
TableColumn<String[],String> nameColumn = new TableColumn();
nameColumn.setText("Name Column");
TableColumn<String[],String> valueColumn = new TableColumn();
valueColumn.setText("Value Column");
tv.getColumns().addAll(nameColumn,valueColumn);
// Add cell value factories
// nameColumn.setCellValueFactory((p)->{
// String[] x = p.getValue();
// return new SimpleStringProperty(x != null && x.length>0 ? x[0] : "<no name>");
// });
//
// valueColumn.setCellValueFactory((p)->{
// String[] x = p.getValue();
// return new SimpleStringProperty(x != null && x.length>1 ? x[1] : "<no value>");
// });
nameColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<String[], String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<String[], String> p) {
String[] x = p.getValue();
if (x != null && x.length>0) {
return new SimpleStringProperty(x[0]);
} else {
return new SimpleStringProperty("<no name>");
}
}
});
valueColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<String[], String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<String[], String> p) {
String[] x = p.getValue();
if (x != null && x.length>1) {
return new SimpleStringProperty(x[1]);
} else {
return new SimpleStringProperty("<no value>");
}
}
});
// Add Data
tv.getItems().addAll(Arrays.asList(data));
// Finish setting the stage
StackPane root = new StackPane();
root.getChildren().add(tv);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Cell Value Factory Example");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
[NOTE: The answer to this other StackOverFlow question is another example of this. ]