Editing a Number cell in a TableView


I have a TableView control which consists of several columns containg different types including Strings and Numbers. I have been trying to write a suitable callback function for an editable Number cell, but I can't get anywhere with it as I get a variety of issues ranging from empty cells to exceptions.

I have read through http://docs.oracle.com/javafx/2/ui_controls/table-view.htm but this only covers String values in cells. The sticking point seems to be lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn());. This line seems to be tailored for Text fields and not for Number fields.

Also, I wish to perform validation on the numbers entered. Does this require a custom callback for the CellFactory in order to do this? If so, how can I develop a callback that accepts Number types and validates them?

Here's a code snippet of what I currently have in my project:

@FXML private TableView<BMIRecord> fxBMITable;
@FXML private TableColumn<BMIRecord, String> fxBMITableDate;
@FXML private TableColumn<BMIRecord, String> fxBMITableTime;
@FXML private TableColumn<BMIRecord, Number> fxBMITableHeight;
@FXML private TableColumn<BMIRecord, Number> fxBMITableWeight;
@FXML private TableColumn<BMIRecord, Number> fxBMITableBMI;

// ...

private void someFunc() {

    /* BMI table callback configuration */
    fxBMITableHeight.setCellValueFactory(new Callback<CellDataFeatures<BMIRecord, String>, ObservableValue<String>>() {
        public ObservableValue<String> call(CellDataFeatures<BMIRecord, String> p) {
            return new SimpleStringProperty(p.getValue().getDateString());

     * ERROR:
     * The method setCellFactory(Callback<TableColumn<BMIRecord,Number>,TableCell<BMIRecord,Number>>)
     * in the type TableColumn<BMIRecord,Number> is not applicable for the arguments
     * (Callback<TableColumn<Object,String>,TableCell<Object,String>>)
    fxBMITableHeight.setOnEditCommit(new EventHandler<CellEditEvent<BMIRecord, Number>>() {
        public void handle(CellEditEvent<BMIRecord, Number> t) {

Thanks for any help in advance.

11/16/2013 3:17:57 PM

Accepted Answer

TextFieldTableCell is type parameterized and has a stringConverter property that you can use to convert to/from String and your desired type.

Try something like:

TextFieldTableCell.<BMIRecord, Number>forTableColumn(new NumberStringConverter())

NumberStringConverter has some additional constructors for specifying the formatting, see the javadocs.

Here's a more complete example:

public class Person {

    public Person(String name0, int age0) {
        name = name0;
        age = age0;
    public String name;
    public int age;

TableView<Person> personTable = new TableView<>();

TableColumn<Person, Number> age = new TableColumn<>();

age.setCellValueFactory(new Callback<CellDataFeatures<Person, Number>, ObservableValue<Number>>() {
    public ObservableValue<Number> call(CellDataFeatures<Person, Number> p) {
        return new SimpleIntegerProperty(p.getValue().age);

age.setCellFactory(TextFieldTableCell.<Person, Number>forTableColumn(new NumberStringConverter()));

This does not work well, though, because NumberStringConverter is so, to be blunt, badly implemented that it simply throws a ParseException at you if you happen to enter a string instead of a number in the cell.

However it should be relatively trivial to implement your own string converter, where you could also do some simple validation (e.g. value should be between 0 and 100).

11/16/2013 5:37:00 PM

jalvafx library:

Solution prevent user from invalid input. Only 0-9, coma and point symbols are allowed. You can set minimun and maximum number value.

enter image description here

Method to use signature:

        TableColumn<T, K> cell,
        BiConsumer<T, Double> changeHandler, 
        String editControlHeader, 
        Double minAllowedValue,
        Double maxAllowedValue, 
        Function<T, Boolean> ignoreEdit)

Mock table:

TableView<String> tableView = new TableView<>();
tableView.getItems().addAll("USA", "Canada", "Brazil");

TableColumn<String, String> country = new TableColumn<>("Country");
TableColumn<String, Integer> column = new TableColumn<>("Some value");


                data -> new SimpleObjectProperty<>(data.getValue()));
                data -> new SimpleObjectProperty<>(800));


BiConsumer<String, Double> changeHandler = (item, newValue) -> {
        System.out.println("New value is " + newValue);
        // Your code

Function<String, Boolean> ignoreEdit = item -> item.equalsIgnoreCase("USA");

TableViewUtils.setEditNumberCellFactory(column, changeHandler, "New value:", 200.0, 800.0, ignoreEdit);

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow