javafx - 为什么在 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;
}
}
结果:
解决方案
推荐阅读
- python-3.x - 将“matplotlib”添加到 cx_Freeze 中的包不起作用
- python - Wagtail:创建自定义 API 端点
- amazon-web-services - Amazon S3 查找用于更新/上传和对象的用户/角色
- c++ - 如何将结构数据成员传递给函数
- neo4j - 将 2 个节点之间的多个关系转换为具有权重的单个关系
- c# - 在 ASP NET Web API 中捕获用户上次请求时间戳
- javascript - 当前从菜单中选择的项目
- vba - 在 VBA 上编辑表单控件标签标题
- nlp - 我可以解释 doc2vec 组件吗?
- javascript - 2d 碰撞检查 javascript,无法正常工作