在TableView中实现Spinner以显示/编辑自定义对象的值 [英] Implement Spinner in TableView to show/edit value of custom object

查看:189
本文介绍了在TableView中实现Spinner以显示/编辑自定义对象的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ObservableList 自定义对象 RecipeObject_Fermentable ,我通过<$向用户显示其属性C $ C>的TableView 。在大多数情况下它运作良好;当我使用新项填充ObservableList时,TableView会显示其内容。

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.

使用 .setCellValueFactory()每列的方法允许我非常容易地在我的 TableView 中将简单对象(字符串和双打)显示为文本。例如,我可以使用...

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"));

问题是,我想显示'重量 Spinner 内的'属性(类型 Double ) tableColumn_rf_weight (并让它显示单位并可以通过文本进行编辑,但这不是主要问题),我无法弄清楚我是如何实际做到这一点的,什么是最好的做法。

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.

我试图通过其他人的帖子提出解决方案,但我无法让它发挥作用。我将此部分归因于不理解每个<$ c的 .setCellFactory() .setCellValueFactory()方法$ c> TableColumn 实际上是和做的,以及它们如何与我的ObservableList中的自定义对象的属性相关联。如果有人可以简单地解释一下,或指出某些事情,我将不胜感激。

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.

那么如何才能让TableView为该列的每个数据条目显示一个Spinner?

以下代码片段将被删除以仅显示有用的信息。如果我遗漏了任何内容,请告诉我。

The following code snippets are cut down to show only the useful information. Let me know if i've missed anything.

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));

提前致谢。

推荐答案

您需要自定义 TableCell 。此外,应该有一种方法将数据传递回项目。这最好通过使用 DoubleProperty 完成,但在您的情况下,您可以使用 JavaBeanDoubleProperty ,如果 null 不允许使用值。)

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 a DoubleProperty but in your case you could work with JavaBeanDoubleProperty, if null values are not allowed).

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>());

这需要将权重设置为但是,非空值。 (我建议使用原始 double 而不是 Double 。)

This requires the weight to be set to a non-null value though. (I recommend using primitive double instead of Double.)

您还需要将列的项目类型更改为 Number

You also need to change the item type of the column to Number:

@FXML
private TableColumn<RecipeObject_Fermentable, Number> tableColumn_rf_weight;

这篇关于在TableView中实现Spinner以显示/编辑自定义对象的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆