【问题标题】:JavaFX Spinner throwing IllegalArgumentException: The start must be <= the endJavaFX Spinner 抛出 IllegalArgumentException:开始必须是 <= 结束
【发布时间】:2016-07-22 06:58:50
【问题描述】:

我在JavaFX 应用程序中使用微调器。我已将listener 添加到我的微调器中,以便始终从Spinner 获取更新的值。这个Spinner 是双值微调器。

 lengthOverAllSpinner.getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
            try {
                lengthOverAllSpinner.getValueFactory().setValue(Double.parseDouble(newValue));
            } catch (NumberFormatException e) {
                lengthOverAllSpinner.getValueFactory().setValue(Double.parseDouble(oldValue));
            }
        });

但是当我尝试从 GUI 编辑我的微调器时(例如,当前值为 340.23)并且当我按下退格键并删除该值直到小数位低于异常时,我总是得到更新的值。不知道为什么会出现这个异常。请帮助:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: The start must be <= the end
at javafx.scene.control.TextInputControl.getText(TextInputControl.java:446)
at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:564)
at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548)
at javafx.scene.control.TextInputControl.deleteText(TextInputControl.java:496)
at javafx.scene.control.TextInputControl.deletePreviousChar(TextInputControl.java:897)
at com.sun.javafx.scene.control.skin.TextFieldSkin.deleteChar(TextFieldSkin.java:589)
at com.sun.javafx.scene.control.behavior.TextFieldBehavior.deleteChar(TextFieldBehavior.java:198)
at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.deletePreviousChar(TextInputControlBehavior.java:311)
at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(TextInputControlBehavior.java:143)
at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(BehaviorBase.java:218)
at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callActionForEvent(TextInputControlBehavior.java:127)
at com.sun.javafx.scene.control.behavior.BehaviorBase.lambda$new$75(BehaviorBase.java:135)
at com.sun.javafx.scene.control.behavior.BehaviorBase$$Lambda$206/1978625466.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3965)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3911)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2502)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:197)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:147)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$349(GlassViewEventHandler.java:228)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$459/610595104.get(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:227)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:956)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/2058534881.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)

提前致谢。

【问题讨论】:

    标签: java exception javafx


    【解决方案1】:

    您的问题与此问题有关:JavaFX Textfield with listener gives: "java.lang.IllegalArgumentException: The start must be <= the end"

    我认为在Spinner 的编辑器TextField 中设置Spinner 值不是一个好主意。

    来自SpinnereditableProperty的文档:

    如果editable为真,一旦用户输入,用户输入将被接收 并按 Enter 键。此时输入被传递给 SpinnerValueFactory 转换器 StringConverter.fromString(String) 方法。此调用的返回值(类型 T)然后被发送到 SpinnerValueFactory.setValue(Object) 方法。如果值为 有效,它将保持为值。如果无效,则值 工厂将需要做出相应的反应并取消此更改。

    因此,默认的工作方式是您只编辑文本,直到您按 Enter 键。在 Enter 键上按下 TextField 的文本被提交,并传递给您的 SpinnervalueFactoryfromString 方法。您可以在工厂处理这种情况:

    lengthOverAllSpinner.getValueFactory().setConverter(new StringConverter<Double>() {
        private final DecimalFormat df = new DecimalFormat("#.####");
    
        @Override public String toString(Double value) {
            // If the specified value is null, return a zero-length String
            if (value == null) {
                return "";
            }
    
            return df.format(value);
        }
    
        @Override public Double fromString(String value) {
            try {
                // If the specified value is null or zero-length, return null
                if (value == null) 
                    return null;
    
                value = value.trim();
    
                if (value.length() < 1) 
                    return null; 
    
                // Perform the requested parsing  
                return df.parse(value).doubleValue();
    
            } catch (Exception ex) {
                return 0.0;
            }
        }
    });
    

    此外,您可以通过在TextField 上使用TextFormatter 来过滤输入以不接受非法字符:

    TextFormatter<Object> textFormatter = new TextFormatter<>(c -> {
    
        if (c.getText().matches("[^0-9.,]+") && !c.getText().isEmpty())
            return null;
    
        SpinnerValueFactory.DoubleSpinnerValueFactory factory = (SpinnerValueFactory.DoubleSpinnerValueFactory) spinner.getValueFactory();
        try {
            Double newVal = Double.parseDouble(c.getControlNewText());
            return (newVal >= factory.getMin() && factory.getMax() >= newVal) ? c : null;
        } catch (Exception ex) {
            c.setText("0.0");
            return c;
        }
    });
    
    spinner.getEditor().setTextFormatter(textFormatter);
    

    此格式化程序只接受数字和“。”和“,”字符。

    【讨论】:

    • 工作就像一个魅力!我在fromString 的末尾添加了一个调用,以根据方法的结果设置文本,而不是在编辑器中添加textFormatter,效果也很好!
    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多