Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javafx 如何将带有TextFormatter和Listener的TextField添加到TableCell中?_Javafx_Cell_Textfield - Fatal编程技术网

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

Javafx 如何将带有TextFormatter和Listener的TextField添加到TableCell中?,javafx,cell,textfield,Javafx,Cell,Textfield,我有一个带整型参数值的水对象。如果尚未创建,则此参数可以为空,等于null。值将存储为整数,但在呈现时,将转换为十进制,并在应用TextFormatter的情况下为用户打印为字符串。用户进行更改后,应将其转换回适当的整数并存储在数据库中 我的水对象: 表的代码: @FXML private TableView<Water> waterTable; @FXML private TableColumn<Water, Integer> valueColumn; @FXML

我有一个带整型参数值的水对象。如果尚未创建,则此参数可以为空,等于null。值将存储为整数,但在呈现时,将转换为十进制,并在应用TextFormatter的情况下为用户打印为字符串。用户进行更改后,应将其转换回适当的整数并存储在数据库中

我的水对象:

表的代码:

@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());
                        }
                    }
                };
            }
        });*/
}
侦听器的代码:


实际上,您可以使用使用StringConverter和UnaryOperator的TextFormatter处理转换和防止无效输入。下面的代码假设您的Water类中有一个ObjectProperty,amountProperty方法将返回它

如果Water.toStringint或Water.toStringInteger方法不存在,则需要实现从int到string的转换,以下代码才能工作

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

}

这假设您的TableCells应始终处于编辑状态。如果情况并非如此,则需要在startEdit/cancelEdit和CommittedIt方法中实现状态更改。

为什么在TextFormatter和TextField声明之后有没有任何方法名称的括号?“以前从来没有见过这样的事。”阿丽亚娜
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;
        }));
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("");
            }
        }));
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);
                    }
                }
            };
        }
    });

}