我将文本字段绑定到整数属性:
@FXML
public TextField countMin;
...
// Limits is my model - countMin is an `IntegerProperty`.
countMin.textProperty().bindBidirectional(limits.countMin, new NumberStringConverter(new LimitFormat()));
Limits
是数据模型。
public class Limits {
// Logger.
protected static final Logger log = LoggerFactory.getLogger(Limits.class);
// The properties.
IntegerProperty countMin = new SimpleIntegerProperty(LimitFormat.NoValue);
...
LimitFormat
看起来像这样 - 它试图将TextField中的空字符串转换为NoValue
中的特殊IntegerProperty
数字。我不认为这是在空案件中调用的,但这里是为了完整性。
public class LimitFormat extends DecimalFormat {
// Special NoValue value.
public static final Integer NoValue = Integer.MAX_VALUE;
// Standard numbers in all other cases.
private static final String limitFormat = "#";
public LimitFormat() {
super(limitFormat);
}
@Override
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
// NoValue becomes empty string.
return ((int) number) == NoValue ? toAppendTo : super.format(number, toAppendTo, pos);
}
@Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
// NoValue becomes empty string.
return number == NoValue ? toAppendTo : super.format(number, toAppendTo, pos);
}
@Override
public Number parse(String source, ParsePosition parsePosition) {
// Empty string should become NoValue.
return source == null || source.isEmpty() ? NoValue : super.parse(source, parsePosition);
}
}
几乎在所有情况下它都可以正常工作,但是当文本字段为空时它似乎被绕过了。
Stack看起来像:
INFO Attempt to set integer property to null, using default value instead.
INFO java.lang.NullPointerException
at javafx.beans.property.IntegerProperty.setValue(IntegerProperty.java:66)
at javafx.beans.property.IntegerPropertyBase.setValue(IntegerPropertyBase.java:52)
at com.sun.javafx.binding.BidirectionalBinding$StringConversionBidirectionalBinding.changed(BidirectionalBinding.java:669)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:347)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1116)
at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1120)
at javafx.scene.control.TextInputControl$TextProperty.invalidate(TextInputControl.java:1060)
at javafx.scene.control.TextInputControl$TextProperty.access$200(TextInputControl.java:1032)
at javafx.scene.control.TextInputControl$1.invalidated(TextInputControl.java:130)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:135)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.scene.control.TextField$TextFieldContent.delete(TextField.java:91)
at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:463)
at javafx.scene.control.TextInputControl.deleteText(TextInputControl.java:417)
at javafx.scene.control.TextInputControl.deletePreviousChar(TextInputControl.java:771)
at com.sun.javafx.scene.control.skin.TextFieldSkin.deleteChar(TextFieldSkin.java:593)
at com.sun.javafx.scene.control.behavior.TextFieldBehavior.deleteChar(TextFieldBehavior.java:195)
at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.deletePreviousChar(TextInputControlBehavior.java:343)
at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(TextInputControlBehavior.java:152)
at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(BehaviorBase.java:222)
...