Java 在 TableView 中编辑数字单元格

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20020037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:22:00  来源:igfitidea点击:

Editing a Number cell in a TableView

javajavafxtableview

提问by Steve

I have a TableViewcontrol 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.

我有一个TableView控件,它由几个包含不同类型的列组成,包括Strings 和Numbers。我一直在尝试为可编辑的 Number 单元格编写一个合适的回调函数,但是我无法使用它,因为我遇到了从空单元格到异常的各种问题。

I have read through http://docs.oracle.com/javafx/2/ui_controls/table-view.htmbut 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.

我已经通读了http://docs.oracle.com/javafx/2/ui_controls/table-view.htm但这仅涵盖单元格中的字符串值。症结似乎是lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn());。这一行似乎是为文本字段而不是数字字段量身定制的。

Also, I wish to perform validation on the numbers entered. Does this require a custom callback for the CellFactoryin order to do this? If so, how can I develop a callback that accepts Number types and validates them?

另外,我希望对输入的数字进行验证。这是否需要自定义回调CellFactory才能执行此操作?如果是这样,我如何开发一个接受 Number 类型并验证它们的回调?

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.

提前感谢您的任何帮助。

采纳答案by Knut Arne Vedaa

TextFieldTableCell is type parameterized and has a stringConverterproperty that you can use to convert to/from String and your desired type.

TextFieldTableCell 是类型参数化的,并且具有一个stringConverter属性,您可以使用该属性来转换为/从字符串和所需的类型。

Try something like:

尝试类似:

TextFieldTableCell.<BMIRecord, Number>forTableColumn(new NumberStringConverter())

NumberStringConverter has some additional constructors for specifying the formatting, see the javadocs.

NumberStringConverter 有一些额外的构造函数用于指定格式,请参阅 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 ParseExceptionat you if you happen to enter a string instead of a number in the cell.

但是,这并不能很好地工作,因为 NumberStringConverter 是这样的,坦率地说,实现得很糟糕,ParseException如果您碰巧在单元格中输入字符串而不是数字,它只会向您抛出 a 。

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

然而,实现您自己的字符串转换器应该相对简单,您还可以在其中进行一些简单的验证(例如,值应介于 0 和 100 之间)。

回答by Zcon

use this

用这个

age.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));

回答by alex valuiskyi

jalvafxlibrary:

jalvafx库:

Solution prevent user from invalid input. Only 0-9, coma and point symbols are allowed. You can set minimun and maximum number value.

解决方案防止用户输入无效。只允许使用 0-9、彗形和点符号。您可以设置最小值和最大值。

enter image description here

在此处输入图片说明

Method to use signature:

签名使用方法:

TableViewUtils.setEditNumberCellFactory(
        TableColumn<T, K> cell,
        BiConsumer<T, Double> changeHandler, 
        String editControlHeader, 
        Double minAllowedValue,
        Double maxAllowedValue, 
        Function<T, Boolean> ignoreEdit)

Mock table:

模拟表:

TableView<String> tableView = new TableView<>();
tableView.getItems().addAll("USA", "Canada", "Brazil");

TableColumn<String, String> country = new TableColumn<>("Country");
TableColumn<String, Integer> column = new TableColumn<>("Some value");

tableView.getColumns().add(country);
tableView.getColumns().add(column);

country.setCellValueFactory(
                data -> new SimpleObjectProperty<>(data.getValue()));
column.setCellValueFactory(
                data -> new SimpleObjectProperty<>(800));

Solution:

解决方案:

BiConsumer<String, Double> changeHandler = (item, newValue) -> {
        System.out.println("New value is " + newValue);
        // Your code
};

Function<String, Boolean> ignoreEdit = item -> item.equalsIgnoreCase("USA");

TableViewUtils.setEditNumberCellFactory(column, changeHandler, "New value:", 200.0, 800.0, ignoreEdit);