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