我有ObservableList
个自定义对象RecipeObject_Fermentable
,我通过TableView
向用户显示其属性。在大多数情况下它运作良好;当我使用新项填充ObservableList时,TableView会显示其内容。
对每列使用.setCellValueFactory()
方法,我可以非常轻松地将简单对象(字符串和双打)显示为TableView
中的文本。例如,我可以使用...
name
类型的属性“String
”
private TableColumn<RecipeObject_Fermentable, String> tableColumn_rf_name;
tableColumn_rf_name.setCellValueFactory(new PropertyValueFactory<>("name"));
问题是,我想在列weight
的Double
内显示“Spinner
”属性(类型为tableColumn_rf_weight
) (并让它显示单位并可以通过文字进行编辑,但这不是主要问题),我无法弄清楚我是如何实际做到这一点的,以及最佳做法是什么。
我试图通过其他人的帖子提出解决方案,但我无法让它发挥作用。我将此部分归因于不理解每个.setCellFactory()
的{{1}}和.setCellValueFactory()
方法实际上是什么和做什么,以及它们如何与我的ObservableList中的自定义对象的属性相关联。如果有人可以简单地解释一下,或指出某些事情,我将不胜感激。
[编辑:我尝试研究这个,但我没有找到任何完整的解释,我可以从我目前对Java和JavaFX的理解中掌握]
那么如何让TableView为该列的每个数据条目显示一个Spinner?
以下代码段被删除以仅显示有用信息。如果我错过了什么,请告诉我。
TableColumn
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);
}
}
提前致谢。
答案 0 :(得分:0)
您需要自定义TableCell
。此外,应该有一种方法将数据传递回项目。最好使用DoubleProperty
,但在您的情况下,如果不允许JavaBeanDoubleProperty
,则可以使用null
。
final JavaBeanDoublePropertyBuilder weightBuilder
= JavaBeanDoublePropertyBuilder.create()
.beanClass(RecipeObject_Fermentable.class)
.name("weight");
tableColumn_rf_weight.setCellValueFactory(cd -> weightBuilder.bean(cd.getValue()).build());
public class DoubleSpinnerCell<T> extends TableCell<T, Number> {
private final Spinner<Double> spinner = new Spinner(0, Double.MAX_VALUE, 0, 0.01);
private boolean ignoreUpdate; // flag preventing updates triggered from ui/initialisation
{
spinner.valueProperty().addListener((o, oldValue, newValue) -> {
if (!ignoreUpdate) {
ignoreUpdate = true;
WritableValue<Number> property = (WritableValue<Number>) getTableColumn().getCellObservableValue((T) getTableRow().getItem());
property.setValue(newValue);
ignoreUpdate = false;
}
});
}
@Override
protected void updateItem(Number item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
ignoreUpdate = true;
spinner.getValueFactory().setValue(item.doubleValue());
setGraphic(spinner);
ignoreUpdate = false;
}
}
}
tableColumn_rf_weight.setCellFactory(c -> new DoubleSpinnerCell<RecipeObject_Fermentable>());
这需要将weight
设置为非空值。 (我建议使用原始double
代替Double
。)
您还需要将列的项类型更改为Number
:
@FXML
private TableColumn<RecipeObject_Fermentable, Number> tableColumn_rf_weight;