当前位置: 首页 > 面试题库 >

在JavaFX Spinner中手动输入文本不会更新值(除非用户按ENTER)

司徒池暝
2023-03-14
问题内容

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

我的想法是为丢失的焦点事件添加一个侦听器,但是我看不到获得对输入值的访问的方法吗?

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

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


问题答案:

不幸的是,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进行验证,在Spinner中也不起作用。可能是某些内部侦听器丢失或微调器尚未更新到相对较新的api-
但是没有挖掘。

更新资料

在使用TextFormatter进行更多操作时,我注意到格式化程序可以
保证

对focusLost
进行提交:

当控件失去焦点或被提交时,将更新该值(仅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行为来强制对spinnerFactory的值进行提交。就像是

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

需要注意的是编辑(无论是打字或以编程方式替换/追加/粘贴文本),并 没有 引发提交-所以,如果提交上文本变化需要此不能使用。



 类似资料:
  • 问题内容: 当我从纯JavaScript更改输入元素的值时,则不会更新角度模型。有什么方法可以通过在更改后手动触发一些事件来触发更新吗? 完整的示例可以在plunkr上找到。单击按钮后,我希望会以某种方式更新。有办法吗? 问题答案: 您不应该这样做(除非用于 测试 ,但即使如此,也请考虑量角器)。以这种方式与angular交互是一个坏主意。但是,如果必须,这是您的操作方法。 一种不同的中间方式是

  • 我的布局中有一个编辑文本,我尝试过在我的编辑文本中放置提示或文本。 当我第一次触摸或点击edittext时,移动键盘弹出输入文本,这是预期的,但edittext中的文本或提示不会被删除。我必须点击2次编辑文本,然后第一次移动键盘弹出,第二次点击删除文本。 我希望在第一次点击本身的文本应该从edittext删除。 例如:假设EditText将初始文本作为用户名,那么当用户第一次单击EditText时

  • 我试图创建编辑文本,当用户按enter键时,它会转到新行,并允许用户输入更多文本。 这是我的设计部分 这是我的代码,但问题是光标位置不会移到下一行。我尝试了,但它不起作用

  • 问题内容: 我是AngularJS的新手,我遇到的一个问题是无法解决,在stackoverflow上也有类似的问题,但似乎并没有帮助我。我基本上有一个可以通过ng- click更新的表单,但是一旦我在任何文本框中输入文本,这些文本框就不再更新。 这是我的HTML 这是有人单击链接时调用的我的函数 问题答案: 您的链接需要登录。 如果我不得不猜测您的问题,则可能与角度范围问题有关。尝试将ng-mod

  • 问题内容: 好的,所以我有一个监视线程,该线程检查ArrayList的大小,并在该大小大于某个数字之后执行一些操作。我现在遇到的问题是,除非我的循环中有打印语句,否则大小值永远不会更新。这是一些代码来显示我到底要做什么。 上面的代码不起作用。它永远不会进入if语句。但是,这很好用: 编辑:getSize()代码: 注意:我有另一个正在运行的线程正在更新并添加到我的t类中的列表中。 有什么帮助吗?当

  • 问题内容: 我正在使用ui- select中的选择框。一切正常,但我想允许手动输入文本,并且不想从列表中的可用值中限制用户。如果我输入文字,它将正确过滤我的列表。但是,当我不单击某个元素并移至下一个字段时,我的文本将被丢弃。 有任何想法吗? 谢谢和问候,亚历克斯 我不想显示我的代码,因为我认为它是不正确的,但是有人要求: 数据存储在中。是要显示的当前字段的编号(我正在动态生成表单)。只需假设它存储