如何将带有TextFormatter和Listener的TextField添加到TableCell中?

时间:2018-06-27 10:38:44

标签: javafx cell textfield

我有一个Water对象,该对象的参数为Integervalue。如果尚未创建,则此参数可以为空,等于null。值将存储为Integer,但是在渲染后将其转换为Decimal,并在应用String的情况下以TextFormatter的形式打印给用户。用户进行更改后,应将其转换回适当的Integer并存储在数据库中。

我的Water对象:

private Integer value; 

enter image description here

表格代码:

@FXML
private TableView<Water> waterTable;

@FXML
private TableColumn<Water, Integer> valueColumn;

@FXML
private void initialize(){
    waterTable.setItems(FXCollections.observableArrayList(thisMonthWaterList));

    //don't know how to implemeny here instead of this code cell with TextField
    /*valueColumn.setCellValueFactory(cellData -> new 
    SimpleIntegerProperty(cellData.getValue().getAmount()).asObject());
        valueColumn.setCellFactory(new Callback<TableColumn<Water,Integer>, 
    TableCell<Water,Integer>>() {

            @Override
            public TableCell<Water, Integer> call(TableColumn<Water, Integer> param) {
                return new TableCell<Water, Integer>(){
                    @Override
                    protected void updateItem(Integer value, boolean empty){
                        super.updateItem(value, empty);
                        if(value==null || empty){
                            setText(null);
                        }else{
                            setText(value.toString());
                        }
                    }
                };
            }
        });*/
}

这是TextFormatter的代码:

TextField.setTextFormatter(new TextFormatter<>(change -> {
            int maxLength = 10;

            if (change.isAdded()) {
                if(change.getControlNewText().length()<=maxLength){
                    if (change.getText().contains(",")) {
                        change.setText(change.getText().replaceAll(",", "."));
                    }
                    change = change.getControlNewText().matches("^\\d*(\\.\\d{0,1})?$") ? change : null;
                }else{
                    if(change.getText().length()==1){
                        change = null;
                    }else{
                        int allowedLength = maxLength - change.getControlText().length();
                        change.setText(change.getText().substring(0, allowedLength));
                    }
                }
            }
            return change;
        }));

Listener的代码:

TextField.focusedProperty().addListener(new FocusChangeListener(TextField, text -> {
            if(text.isEmpty()){
                TextField.setText(Water.getAreaFormat());
            }else{
                TextField.setText(Water.toString(TextField.getText()));
            }
            thisObject.setValue(Water.toInt(TextField.getText()));
            WaterDA.update(thisObject);
        }, text -> {
            if(text.equals(Water.getWaterFormat())){
                TextField.setText("");
            }
        }));

1 个答案:

答案 0 :(得分:1)

实际上,您可以使用TextFormatterStringConverter使用UnaryOperator处理转换并防止无效输入。以下代码假定您在ObjectProperty<Integer>类中有一个Water,并且amountProperty()方法将其返回。

如果不存在Water.toString(int)Water.toString(Integer)方法,则需要实现从int到字符串的转换,以便以下代码起作用。

private static final StringConverter<Integer> VALUE_CONVERTER = new StringConverter<Integer>() {

    @Override
    public String toString(Integer object) {
        return object == null ? Water.getAreaFormat() : Water.toString(object);
    }

    @Override
    public Integer fromString(String string) {
        return Water.toInt(string);
    }

};

// filter copied unmodified from your code
private static final UnaryOperator<TextFormatter.Change> VALUE_FILTER = change -> {
    int maxLength = 10;

    if (change.isAdded()) {
        if(change.getControlNewText().length() <= maxLength){
            if (change.getText().contains(",")) {
                change.setText(change.getText().replaceAll(",", "."));
            }
            change = change.getControlNewText().matches("^\\d*(\\.\\d{0,1})?$") ? change : null;
        } else {
            if (change.getText().length() == 1){
                change = null;
            } else {
                int allowedLength = maxLength - change.getControlText().length();
                change.setText(change.getText().substring(0, allowedLength));
            }
        }
    }
    return change;
};

@FXML
private TableColumn<Water, Integer> valueColumn;

@FXML
private void initialize(){
    waterTable.setItems(FXCollections.observableArrayList(thisMonthWaterList));

    valueColumn.setCellValueFactory(cellData -> cellData.getValue().amountProperty());
    valueColumn.setCellFactory(new Callback<TableColumn<Water, Integer>, TableCell<Water, Integer>>() {

        @Override
        public TableCell<Water, Integer> call(TableColumn<Water, Integer> param) {
            return new TableCell<Water, Integer>() {

                private final TextFormatter<Integer> formatter;
                private final TextField textField;

                {
                    textField = new TextField();
                    formatter = new TextFormatter<>(VALUE_CONVERTER, null, VALUE_FILTER);
                    textField.setTextFormatter(formatter);
                    formatter.valueProperty().addListener((o, oldValue, newValue) -> {
                        Water water = (Water) getTableRow().getItem();
                        if (!Objects.equals(water.getAmount(), newValue)) {
                             // update item and db, if value was modified
                             water.setAmount(newValue);
                             WaterDA.update(water);
                        }
                    });
                }

                @Override
                protected void updateItem(Integer value, boolean empty){
                    super.updateItem(value, empty);
                    if (empty){
                        setGraphic(null);
                    } else {
                        setGraphic(textField);
                        formatter.setValue(value);
                    }
                }
            };
        }
    });

}

这假设您的TableCell应该始终处于“编辑状态”。如果不是这种情况,则需要在startEdit / cancelEditcommitEdit方法中实现状态更改。