在JavaFX Spinner中手动输入文本不会更新值(除非用户按ENTER键) [英] Manually typing in text in JavaFX Spinner is not updating the value (unless user presses ENTER)

查看:252
本文介绍了在JavaFX Spinner中手动输入文本不会更新值(除非用户按ENTER键)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在用户明确按Enter之前,Spinner控件似乎不会更新手动键入的值。因此,他们可以键入一个值(不按回车键)退出控件,并提交表单,并且微调器中显示的值不是微调器的值,它是旧值。

It seems that the Spinner control does not update a manually typed-in value until the user explicitly presses enter. So, they could type in a value (not press enter) exit the control, and submit the form, and the value displayed in the spinner is NOT the value of the Spinner, it is the old value.

我的想法是为丢失的焦点事件添加一个监听器,但我看不到一种获取输入值的方法?

My idea was to add a listener to the lost focus event, but I can't see a way to gain access to the typed-in value?

spinner.focusedProperty().addListener((observable, oldValue, newValue) -> 
{
    //if focus lost
    if(!newValue)
    {
        //somehow get the text the user typed in?
    }
});

这是奇怪的行为,它似乎违反了GUI微调控件的约定。

This is odd behavior, it seems to go against the convention of a GUI spinner control.

推荐答案

不幸的是,Spinner的行为并不像预期的那样:在大多数操作系统中,它应该在焦点丢失时提交编辑后的值。更不幸的是,它没有提供任何配置选项来轻松使其按预期运行。

Unfortunately, Spinner doesn't behave as expected: in most OS, it should commit the edited value on focus lost. Even more unfortunate, it doesn't provide any configuration option to easily make it behave as expected.

因此我们必须手动将侦听器中的值提交给focusedProperty。从好的方面来看,Spinner已经有代码这样做 - 它是私有的,但我们必须c& p它

So we have to manually commit the value in a listener to the focusedProperty. On the bright side, Spinner already has code doing so - it's private, though, we have to c&p it

/**
 * 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()

我原本希望...嗯...提交价值,这没有效果。实现(final!)以更新textFormatter的值(如果可用)。即使您使用 textFormatter进行验证,也无法在Spinner中工作。可能是一些内部听众丢失或者锭床工人还没有更新到相对较新的api - 但是没有挖掘。

which I would have expected to ... well ... commit the value, which has no effect. It's (final!) implemented to update the value of the textFormatter if available. Doesn't work in the Spinner, even if you use a textFormatter for validation. Might be some internal listener missing or the spinner not yet updated to the relatively new api - didn't dig, though.

更新

在使用TextFormatter玩一点时,我注意到格式化程序 保证在focusLost上提交

While playing around a bit more with TextFormatter I noticed that a formatter guarantees to commit on focusLost:


当控件失去焦点或提交时,值会更新(仅限TextField)

The value is updated when the control loses its focus or it is commited (TextField only)

这确实有效,因为我们可以在格式化程序的valueProperty中添加一个监听器,以便在提交值时得到通知:

Which indeed works as documented such that we could add a listener to the formatter's valueProperty to get notified whenever the value is committed:

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以编程方式调用(这是未记录的行为!)

回到微调器:我们可以使用formatter的值的commit-on-focusLost行为来强制提交spinnerFactory的值。类似

Coming back to the spinner: we can use this commit-on-focusLost behaviour of a formatter's value to force a commit on the spinnerFactory's value. Something like

// 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());

请注意,编辑(键入或以编程方式替换/附加/粘贴文本)触发提交 - 因此,如果需要进行文本更改,则无法使用此提示。

Note that editing (either typing or programmatically replacing/appending/pasting text) does not trigger a commit - so this cannot be used if commit-on-text-change is needed.

这篇关于在JavaFX Spinner中手动输入文本不会更新值(除非用户按ENTER键)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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