I have a TableView
control which consists of several columns containg different types including String
s and Number
s. 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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With