TableView and ListValueFactory in JavaFX

The TableView control is pretty complete to use and very convenient. But the classical use of it specify that a line is represented by an instance of an Object, usually a property bean. But in some cases it would be very useful to have a line composed by multiple instances of a specific class, i.e. having an instance per column, and each column should display a particular property of your instance. A concrete example would be the management interface of translations in NetBeans. Indeed, this screen display all properties files of a particular resource bundle, having a column for the translations keys and as many columns as needed to display the translations for each keys.


As said above, we could need an instance of object per column, meaning multiple instances per line. So a line of the TableView should be a List<? extends Object>. The problem is to know which data to display in a particular column.


As you may know, you can set CellValueFactory on a TableColumn, which will display the value in the cell. For example, you can set a PropertyValueFactory that will look for a property of a bean, and will display it. But that works if you have a single Object per line, not a collection. So we will create our own implementation that will check a property of a bean inside a list.

public class ListValueFactory<T, V> implements Callback<TableColumn.CellDataFeatures<List<T>, V>, ObservableValue<V>> {
  private String propertyName;

  public ListValueFactory(String propertyName) {
    this.propertyName = propertyName;
  public ObservableValue<V> call(TableColumn.CellDataFeatures<List<T> , V> p) {
    int index = 0;
    ListIterator<TableColumn<List<T>, ?>> iterator = 
    TableColumn tmpColumn;
    while(iterator.hasNext()) {
      tmpColumn =;

      if(tmpColumn == p.getTableColumn())

    T object = p.getValue().get(index);

    try {
      Method method = object.getClass().getMethod(propertyName.concat("Property"));
      return (Property<V>) method.invoke(object);
    } catch (Exception ex) {
      Logger.getLogger(ListValueFactory.class.getName()).log(Level.SEVERE, null, ex);
      return null;

As you can see, the implementation is totally generic. First, we try to know the index of the column and we suppose that this index is the same index of the data in the list of data. WARNING: this is totally wrong if, in your UI, you move columns ; so take this into consideration because the implementation is not shown here. Once we have the index, we look for the data in the list, and finally, using so introspection, we look for the getter of the property in order to get the value. And that’s it.


To use this implementation in your code, you juste have to do the following:

TableView<List<Person>> tableView = new TableView<>();
TableColumn<String> columnOne = new TableColumn<>("First name one");
columnOne.setCellValueFactory(new ListValueFactory<List<Person>, String>("firstName"));
TableColumn<String> columnTwo = new TableColumn<>("First name two");
columnTwo.setCellValueFactory(new ListValueFactory<List<Person>, String>("firstName"));
tableView.getColumns().addAll(columnOne, columnTwo);