I have an ObservableList
of custom objects RecipeObject_Fermentable
, whose properties I am displaying to the user through a TableView
. For the most part it works well; when I populate the ObservableList with a new item, the TableView displays its contents.
Using the .setCellValueFactory()
method for each column allows me to display the simple objects (Strings and Doubles) as text in my TableView
very easily. For instance, I can access property 'name
' of type String
with...
private TableColumn<RecipeObject_Fermentable, String> tableColumn_rf_name;
tableColumn_rf_name.setCellValueFactory(new PropertyValueFactory<>("name"));
The problem is, I want to show the 'weight
' property (of type Double
) inside a Spinner
for column tableColumn_rf_weight
(and have it display units and be editable by text, but that’s not the main issue), and I cannot work out how I can actually do this, and what is best practise.
I have tried to come up with a solution through other people’s posts, but I cannot get it to work. I attribute this partly to not understanding what the .setCellFactory()
and .setCellValueFactory()
methods for each TableColumn
actually are and do, and how they link with the properties of the custom objects in my ObservableList. If someone could briefly explain this, or point to something that does, I would be grateful.
[EDIT: I DID try researching this but I didn't find any full explanation that I could grasp from my current understanding of Java and JavaFX]
So how can I get the TableView to display a Spinner for each data entry of that column?
The following code snippets are cut down to show only the useful information. Let me know if i've missed anything.
The custom object
public class RecipeObject_Fermentable {
// Object properties
private String name; // Displayed and referenced name of the fermentable
private Double srm; // Colour of fermentable in SRM
private Double pkgl; // Specific gravity points per kg per liter
private Double weight; // Weight in kilograms
private Double percent; // Total percent to grain bill as percentage
private BooleanProperty lateadd;// Late addition toggle
// Constructor
public RecipeObject_Fermentable(String name, Double weight, Double srm, Double pkgl, Double contribution, boolean lateadd) {
this.name = name;
this.srm = srm;
this.pkgl = pkgl;
this.weight = weight;
this.percent = contribution;
this.lateadd = new SimpleBooleanProperty(lateadd);
}
// Constructor from fermentable object
public RecipeObject_Fermentable(Fermentable f) {
this.name = f.getName();
this.srm = f.getSrm();
this.pkgl = f.getPkgl();
if (f.getType().equals(FermType.GRAIN)) {
if (f.getSubtype().equals(FermSubtype.BASE_MALT)) {
this.weight = Double.valueOf(5);
} else {
this.weight = Double.valueOf(1);
}
} else {
this.weight = Double.valueOf(0);
}
this.percent = Double.valueOf(0);
this.lateadd = new SimpleBooleanProperty(false);
}
public String getName() {
return this.name;
}
public Double getSrm() {
return this.srm;
}
public Double getPkgl() {
return this.pkgl;
}
public Double getWeight() {
return this.weight;
}
public Double getContribution() {
return this.percent;
}
public ObservableBooleanValue isLateadd() {
return lateadd;
}
public void setName(String name) {
this.name = name;
}
public void setSrm(Double srm) {
this.srm = srm;
}
public void setPkgl(Double pkgl) {
this.pkgl = pkgl;
}
public void setWeight(Double value) {
this.weight = value;
}
public void setContribution(Double contribution) {
this.percent = contribution;
}
public void setLateadd(Boolean checked) {
this.lateadd.set(checked);
}
}
Other code in my controller
// Link and define FXML objects for tableView and its columns
@FXML
private TableView<RecipeObject_Fermentable> tableview_recipeFermentables;
@FXML
private TableColumn<RecipeObject_Fermentable, String> tableColumn_rf_name;
@FXML
private TableColumn<RecipeObject_Fermentable, Double> tableColumn_rf_weight;
@FXML
private TableColumn<RecipeObject_Fermentable, Double> tableColumn_rf_percent;
@FXML
private TableColumn<RecipeObject_Fermentable, Boolean> tableColumn_rf_lateAddition;
// Set up observable list of custom object
private ObservableList<RecipeObject_Fermentable> fermentables_recipe =
FXCollections.observableArrayList()
// Set up table data
tableview_recipeFermentables.setItems(fermentables_recipe);
tableColumn_rf_name.setCellValueFactory(new PropertyValueFactory<>("name"));
// ---> tableColumn_rf_weight.setCellValueFactory();
// ---> tableColumn_rf_weight.setCellFactory();
tableColumn_rf_percent.setCellValueFactory(new PropertyValueFactory<>("percent"));
tableColumn_rf_lateAddition.setCellValueFactory(p->p.getValue().isLateadd());
tableColumn_rf_lateAddition.setCellFactory(CheckBoxTableCell.forTableColumn( tableColumn_rf_lateAddition));
Thanks in advance.
You need a custom
TableCell
. Additionally there should be a way to pass the data back to the item. This is best done by using aDoubleProperty
but in your case you could work withJavaBeanDoubleProperty
, ifnull
values are not allowed).This requires the
weight
to be set to a non-null value though. (I recommend using primitivedouble
instead ofDouble
.)Edit
You also need to change the item type of the column to
Number
: