不幸的是,Spinner 的行为不如预期:在大多数操作系统中,它应该在焦点丢失时提交编辑的值。更不幸的是,它没有提供任何配置选项来轻松使其按预期运行。
所以我们必须手动将侦听器中的值提交给focusedProperty。从好的方面来说,Spinner 已经有这样做的代码 - 它是私有的,但我们必须 c&p 它
/**
* c&p from Spinner
*/
private <T> void commitEditorText(Spinner<T> spinner) {
if (!spinner.isEditable()) return;
String text = spinner.getEditor().getText();
SpinnerValueFactory<T> valueFactory = spinner.getValueFactory();
if (valueFactory != null) {
StringConverter<T> converter = valueFactory.getConverter();
if (converter != null) {
T value = converter.fromString(text);
valueFactory.setValue(value);
}
}
}
// useage in client code
spinner.focusedProperty().addListener((s, ov, nv) -> {
if (nv) return;
//intuitive method on textField, has no effect, though
//spinner.getEditor().commitValue();
commitEditorText(spinner);
});
注意有一个方法
textField.commitValue()
我本来希望......好吧......提交价值,这没有效果。它(最终!)实施以更新 textFormatter 的值(如果可用)。即使您使用textFormatter for validation,在微调器中也不起作用。可能是缺少一些内部侦听器,或者微调器尚未更新到相对较新的 api - 不过没有挖掘。
更新
在使用 TextFormatter 进行更多操作时,我注意到在 focusLost 上的格式化程序 guarantees to commit:
当控件失去焦点或提交时更新值(仅限TextField)
这确实像记录的那样工作,这样我们就可以向格式化程序的 valueProperty 添加一个侦听器,以便在提交值时得到通知:
TextField field = new TextField();
TextFormatter fieldFormatter = new TextFormatter(
TextFormatter.IDENTITY_STRING_CONVERTER, "initial");
field.setTextFormatter(fieldFormatter);
fieldFormatter.valueProperty().addListener((s, ov, nv) -> {
// do stuff that needs to be done on commit
} );
提交的触发器:
- 用户点击 ENTER
- 控制失去焦点
- field.setText 以编程方式调用(这是未记录的行为!)
回到微调器:我们可以使用格式化程序值的这种 commit-on-focusLost 行为来强制提交微调器工厂的值。类似的东西
// normal setup of spinner
SpinnerValueFactory factory = new IntegerSpinnerValueFactory(0, 10000, 0);
spinner.setValueFactory(factory);
spinner.setEditable(true);
// hook in a formatter with the same properties as the factory
TextFormatter formatter = new TextFormatter(factory.getConverter(), factory.getValue());
spinner.getEditor().setTextFormatter(formatter);
// bidi-bind the values
factory.valueProperty().bindBidirectional(formatter.valueProperty());
请注意,编辑(键入或以编程方式替换/附加/粘贴文本)不会触发提交 - 因此,如果需要提交文本更改,则不能使用。