Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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() {
    fxBMITable.setEditable(true);

    /* 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.setCellFactory(TextFieldTableCell.forTableColumn());
    fxBMITableHeight.setOnEditCommit(new EventHandler<CellEditEvent<BMIRecord, Number>>() {
        @Override
        public void handle(CellEditEvent<BMIRecord, Number> t) {
            ((BMIRecord)t.getTableView().getItems().get(t.getTablePosition().getRow())).setHeight(t.getNewValue().doubleValue());
        }
    });
}

Thanks for any help in advance.

like image 381
Steve Avatar asked Nov 16 '13 15:11

Steve


1 Answers

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>>() {
    @Override
    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).

like image 114
Knut Arne Vedaa Avatar answered Oct 15 '22 10:10

Knut Arne Vedaa