Java 8 DatePicker 和可编辑的 ComboBox 行为在 8u51 和 8u60 之间发生变化 [英] Java 8 DatePicker and editable ComboBox behavior change between 8u51 and 8u60

查看:28
本文介绍了Java 8 DatePicker 和可编辑的 ComboBox 行为在 8u51 和 8u60 之间发生变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We have searched this forum and the web extensively and have not found anything related to this issue so I felt compelled to post this question here...

在 Java 8 u51 和 u60 发布之间,我们观察到 JavaFX8 DatePicker 和可编辑 ComboBox 元素的功能发生了重大的行为变化.

We have observed a major behavioral change with regard to the functionality of both the JavaFX8 DatePicker and editable ComboBox elements between the release of Java 8 u51 and u60.

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

Running under u51 you could enter a date such as 12/30/1970 in a DatePicker and tab to the next U.I. element and the data would automatically be saved and if the date was bound to an age calculation TextField the age would update. The same for editable ComboBox elements. However running under u60 the user MUST press ENTER after a data change on either the DatePicker or editable ComboBox, otherwise the data is not saved. Tabbing to the next U.I. element or a mouse click outside of the U.I. element and the data is lost, replaced by what was previously saved in that element prior to the edit.

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

So my question is, has anyone else noticed this critical behavioral change and if so feel this is a bug in u60 or a direction Oracle is deliberately taking for some reason?

最后是否有解决方法,可能是事件处理程序的形式,可以在这些元素失去焦点之前模拟ENTER"键按下?

Finally is there a work around, perhaps in the form of an event handler that can simulate an 'ENTER' key press prior to loss of focus of these elements?

预先感谢您的考虑.

推荐答案

ComboBoxPopupControl(实际上是所有类似组合控件的相关基础皮肤)的实现在 u40 和 u60 之间发生了变化:textField - 包括所有内部接线 - 从混凝土皮肤(如 fi ComboBoxListViewSkin)拉到底座中.

The implementation of ComboBoxPopupControl (which in fact is the relevant base skin for all combo-like controls) changed somewhere between u40 and u60: the textField - including all internal wirings - was pulled up from the concrete skins (like f.i. ComboBoxListViewSkin) into the base.

除此之外,ENTER 的处理程序也发生了变化:

Along with this mere technicality the handler for ENTER was changed:

  • was:将组合接收到的所有 keyEvents 转发到文本字段
  • is:处理和使用基础皮肤中的 ENTER.此实现手动将字段中的输入文本提交给组合的值.

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

A dirty (!because needs access to the internal package com.sun.whatever.skin) way out is a custom skin that listens to the focusProperty and calls the commit method, something like:

public class MyComboSkin<T> extends ComboBoxListViewSkin<T> {

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

应用自定义皮肤的好处是可以通过添加样式表每个场景应用一次:

The advantage of applying a custom skin is that it can be applied once per scene by adding a 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) 

顺便说一句:我认为核心中的新实现相当脏 - 所有 keyBindings 应该在 XXBehaviour 中处理,或者留给较低级别​​的孩子(如 textField 本身).行为的变化(针对 8u45 进行了验证)可能被视为错误.

BTW: I think the new implementation in core is rather dirty - all keyBindings should be handled either in the XXBehaviour or alternatively left to the lower-level children (like the textField itself). The change in behaviour (verified against 8u45) might be considered a bug.

更新

另一种技巧是在组合的编辑器上使用 TextFormatter 并将它的 valueProperty 与组合的 valueProperty 双向绑定,例如:

An alternative trick is using a TextFormatter on the combo's editor and bidi-bind it's valueProperty to the combo's valueProperty, something like:

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

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

This does work because the formatter guarantees to commit - aka: sync its own value to the textField's text - on focusLost (more details in a similar requirement for Spinner) Note that a side-effect of this approach is that the text is committed on navigation inside the drop-down which might or not be acceptable depending on context. Also, it's more experimenting with TextFormatters than a dedicated workaround - needs the same per-instance manipalution as the workaround in the other solution by Scott.

bug 已在 jdk9 中得到修复并已向后移植 8u72,因此任何解决方法希望是短暂的,选择一次或其他并根据需要进行肮脏可能是品味问题:-)

The bug is fixed in jdk9 and backported 8u72, so any workaround hopefully is short-lived, choosing the once or other and going as dirty as necessary is likely a matter of taste :-)

这篇关于Java 8 DatePicker 和可编辑的 ComboBox 行为在 8u51 和 8u60 之间发生变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆