The tutorial you mention uses a PropertyValueFactory. That is not applicable here as that only introspects on a given class, but if you look at the documentation for that class it includes the following long form:
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name");
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return p.getValue().firstNameProperty();
}
});
}
So you can use the same concept with your data class to retrieve the appropriate field from the user object of the data object:
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Data, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Data, String> data) {
// data.getValue() returns the Data instance for a particular TableView row
return data.getValue().getUser().firstNameProperty();
}
});
}
Some of the ugliness can be removed if you use Java 8 lambdas.
If your user object doesn't have property accessors for the values, but only getters, you can wrap the result in a ReadOnlyObjectWrapper as described in the PropertyValueFactory documentation:
return new ReadOnlyObjectWrapper(data.getValue().getUser().getFirstName());
This is fine if your table is not editable and you don't want the table data to change automatically If the underlying field changes, otherwise the property accessor based method is preferred.
TableViewfor each data type, and switch the table views in and out of the scene graph (instead of using a single table view, and replacing its data, which I think is what you're proposing in the question).