Java 8 DatePicker和可编辑的ComboBox行为在8u51和8u60之间变化

我们已经广泛搜索了这个论坛和网站,但没有发现任何与此问题有关的内容,所以我觉得有必要在这里发布这个问题…

我们观察到Java 8 u51和u60版本之间JavaFX8 DatePicker和可编辑ComboBox元素的function方面的主要行为变化。

在u51下运行,您可以在DatePicker和tab中输入日期(例如12/30/1970)到下一个UI元素,数据将自动保存,如果日期绑定到年龄计算TextField,则年龄将更新。 可编辑的ComboBox元素也是如此。 但是在u60下运行时,用户必须在DatePicker或可编辑ComboBox上更改数据后按ENTER键 ,否则数据不会保存。 在UI元素外部切换到下一个UI元素或鼠标单击,数据将丢失,取而代之前在编辑之前保存在该元素中的内容。

所以我的问题是,是否还有其他人注意到这种关键的行为改变,如果是这样的话,我觉得这是u60中的一个错误或Oracle出于某种原因故意采取的方向?

最后有一个解决方法,也许是以事件处理程序的forms,可以在失去这些元素的焦点之前模拟“ENTER”键按下?

提前感谢您的考虑。

ComboBoxPopupControl(实际上是所有类似combo的控件的相关基础皮肤)的实现在u40和u60之间的某处发生了变化:textField – 包括所有内部布线 – 从具体皮肤(如fi ComboBoxListViewSkin)拉到底座中。

除了这种纯粹的技术性,ENTER的处理程序也发生了变化:

  • 是:将组合接收的所有keyEvent转发到textField
  • 是:处理并消耗基础皮肤中的ENTER。 此实现手动将输入文本从字段提交到组合的值。

一个脏(!因为需要访问内部包com.sun.whatever.skin)出路是一个自定义皮肤,它监听focusProperty并调用commit方法,如:

public class MyComboSkin extends ComboBoxListViewSkin { public MyComboSkin(ComboBox comboBox) { super(comboBox); getSkinnable().focusedProperty().addListener((source, ov, nv) -> { if (!nv) { setTextFromTextFieldIntoComboBoxValue(); } }); } } 

应用自定义皮肤的优点是可以通过添加styleSheet在每个场景中应用一次:

 // defining the skin in a css mycomboskin.css .combo-box { -fx-skin: "mypackage.MyComboSkin"; } // apply to a scene String commitCSS = getClass().getResource("mycomboskin.css").toExternalForm(); scene.getStylesheets().add(commitCSS); // or to the application (using internal api again ;-) StyleManager.getInstance().addUserAgentStylesheet(commitCSS) 

顺便说一句:我认为核心中的新实现相当脏 – 所有的keyBinding 都应该在XXBehaviour中处理,或者留给较低级别​​的子节点(如textField本身)。 行为的变化(针对8u45validation)可能被视为错误。


更新

另一个技巧是在组合编辑器上使用TextFormatter并将它的valueProperty绑定到组合的valueProperty,类似于:

 TextFormatter formatter = new TextFormatter<>(comboBox.getConverter()); comboBox.getEditor().setTextFormatter(formatter); comboBox.valueProperty().bindBidirectional(formatter.valueProperty()); 

这确实有效,因为格式化程序保证提交 – 也就是:将自己的值同步到textField的文本 – 在focusLost上(更多细节在Spinner的类似要求中 )请注意,这种方法的副作用是文本在导航时提交在下拉列表中,根据上下文可能或不可接受。 此外,它更多地使用TextFormatters进行实验,而不是专门的解决方法 – 需要与Scott的其他解决方案中的解决方法相同的每个实例操作。


这个bug在jdk9和backported 8u72中得到修复,所以任何解决方法都希望是短暂的,选择一次或其他并且根据需要变得很脏可能是品味问题:-)

这是我的解决方法:

  combo.getEditor().focusedProperty().addListener((obs, old, isFocused) -> { if (!isFocused) { combo.setValue(combo.getConverter().fromString(combo.getEditor().getText())); } }); 

正如官方错误报告中所指出的 ,您可能需要检查是否已设置该值以避免再次调用它的任何潜在副作用。