首页 > 解决方案 > 为什么在 TextFormatter 中没有调用 toString?

问题描述

我想创建一个可以输入任何数字的字段,它将被转换为#.#(点后有一个数字的十进制)并存储为整数。

问题:如果用户已经有数字5.0并擦除0,在失去焦点后,它将保持为5.,因为toString没有调用转换器的方法。

但是,如果用户拥有数字55.0并擦除0,则在失去焦点后,toString将调用方法并且数字再次变为55.0

我的Main.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane prefHeight="300.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="home.accounting.view.MainController">
   <children>
      <TableView fx:id="waterTable" layoutX="31.0" layoutY="50.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="30.0" AnchorPane.rightAnchor="30.0" AnchorPane.topAnchor="50.0">
        <columns>
          <TableColumn fx:id="flat" maxWidth="75.0" prefWidth="75.0" text="Flat" />
          <TableColumn fx:id="newValue" prefWidth="185.0" text="New Value" />
            <TableColumn fx:id="oldValue" prefWidth="185.0" text="Old Value" />
        </columns>
      </TableView>
   </children>
</AnchorPane>

MainApp.java

public class MainApp extends Application {

    private AnchorPane rootLayout;

    @Override
    public void start(Stage primaryStage) {

        primaryStage.setTitle("Test");
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(MainApp.class.getResource("view/Main.fxml"));
            rootLayout = (AnchorPane)loader.load();
            Scene scene = new Scene(rootLayout);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

MainController.java

public class MainController {

    @FXML
    private TableView<Water> waterTable;

    @FXML
    private TableColumn<Water, Integer> flat;

    @FXML
    private TableColumn<Water, Integer> newValue;

    @FXML TableColumn<Water, Integer> oldValue;

    private List<Water> waterList;

    private static final String waterFormat = "0.0";

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

        @Override
        public String toString(Integer object) {
            System.out.println("TO STRING CONVERTER: "+object);
            return object == null ? "" : convertToString(object);
        }

        @Override
        public Integer fromString(String string) {
            System.out.println("TO INTEGER CONVERTER:"+string+";"+string.isEmpty());
            return string.isEmpty() ? null : convertToInt(string);
        }

    };


    @FXML
    private void initialize(){
        createObjects();
        setupCells();
        createRows();
    }

    private void createObjects(){
        waterList = new ArrayList<>();

        for(int i=0; i<5; i++){
            waterList.add(new Water(i+1));
        }
    }

    private void setupCells(){
        flat.setCellValueFactory(cellData -> new ReadOnlyObjectWrapper<>(cellData.getValue().getFlat()));

        newValue.setCellValueFactory(cellData -> new ReadOnlyObjectWrapper<>(cellData.getValue().getNewValue()));
        newValue.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, null);
                        textField.setTextFormatter(formatter);
                    }
                    @Override
                    protected void updateItem(Integer value, boolean empty){
                        super.updateItem(value, empty);
                        if (empty){
                            setGraphic(null);
                        } else {
                            setGraphic(textField);
                            formatter.setValue(value);
                        }
                    }
                };   
            }
        });
    }

    private void createRows(){
        waterTable.setItems(FXCollections.observableArrayList(waterList));
    }

    private static int convertToInt(String water){
        int waterInt = 0;
        try{
            BigDecimal userInput = new BigDecimal(water);
            DecimalFormat waterConverter = new DecimalFormat(waterFormat);
            String waterString = waterConverter.format(userInput);
            waterInt = Integer.parseInt(String.valueOf(new BigDecimal(waterString).movePointRight(1)));
        }catch (Exception e) {
            e.printStackTrace();
        }

        return waterInt;
    }

    private static String convertToString(int water){
        System.out.println("TO STRING CONVERTER: "+water);
        BigDecimal userInput = new BigDecimal(water);
        DecimalFormat waterConverter = new DecimalFormat(waterFormat);
        String waterString = waterConverter.format(userInput.movePointLeft(1));
        return waterString;
    }
}

Water.java

public class Water {

    private Integer flat;
    private Integer newValue;
    private Integer oldValue;

    public Water(Integer flat){
        this.flat = flat;
    }

    public Integer getFlat() {
        return flat;
    }

    public void setFlat(Integer flat) {
        this.flat = flat;
    }

    public Integer getNewValue() {
        return newValue;
    }

    public void setNewValue(Integer newValue) {
        this.newValue = newValue;
    }

    public Integer getOldValue() {
        return oldValue;
    }

    public void setOldValue(Integer oldValue) {
        this.oldValue = oldValue;
    }
}

结果:

在此处输入图像描述

标签: javafxconvertertextfield

解决方案


推荐阅读