【问题标题】:JavaFX Textfield with listener gives: "java.lang.IllegalArgumentException: The start must be <= the end"带有侦听器的 JavaFX 文本字段给出:“java.lang.IllegalArgumentException:开始必须是 <= 结束”
【发布时间】:2015-08-08 12:38:24
【问题描述】:

我遇到了一个异常,但不明白是什么原因造成的。这是一个带有 FXML 文件的 FX 应用程序。在应用程序的 init() 部分,我向文本字段添加了一个侦听器,该侦听器调用一个函数,该函数使用正则表达式监视字符串的模式。

tf.textProperty().addListener(
        (observable, oldValue, newValue) -> {
            handleInput(newValue);
        });

功能:

private void handleInput(String s) {

            s = s.toUpperCase();
            Matcher matcher = Pattern
                    .compile(
                            "^[A-Z]{2}(20|21|22|23|[0-1]\\d)[0-5]\\d(20|21|22|23|[0-1]\\d)[0-5]\\d(T\\s|C\\s|TC|CT|\\s\\s)$")
                    .matcher(s);

            if (matcher.find()) {

                    // do something

                    // then clear the textfield
                    tf.clear();

                } else {
                    // do something else
                }
            }

它可以工作,但如果匹配器匹配,它会给我一个例外。

例外:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: The start must be <= the end
    at javafx.scene.control.TextInputControl.getText(Unknown Source)
    at javafx.scene.control.TextInputControl.updateContent(Unknown Source)
    at javafx.scene.control.TextInputControl.replaceText(Unknown Source)
    at com.sun.javafx.scene.control.skin.TextFieldSkin.replaceText(Unknown Source)
    at com.sun.javafx.scene.control.behavior.TextFieldBehavior.replaceText(Unknown Source)
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.defaultKeyTyped(Unknown Source)
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(Unknown Source)
    at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(Unknown Source)
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callActionForEvent(Unknown Source)
    at com.sun.javafx.scene.control.behavior.BehaviorBase.lambda$new$75(Unknown Source)
    at com.sun.javafx.scene.control.behavior.BehaviorBase$$Lambda$88/1978656397.handle(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.event.Event.fireEvent(Unknown Source)
    at javafx.scene.Scene$KeyHandler.process(Unknown Source)
    at javafx.scene.Scene$KeyHandler.access$1800(Unknown Source)
    at javafx.scene.Scene.impl_processKeyEvent(Unknown Source)
    at javafx.scene.Scene$ScenePeerListener.keyEvent(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$349(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$349/1135388943.get(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(Unknown Source)
    at com.sun.glass.ui.View.handleKeyEvent(Unknown Source)
    at com.sun.glass.ui.View.notifyKey(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)}

我已经尝试了一些我在其他帖子中找到的建议,比如在将字符串提供给匹配器之前检查字符串:

if (!tf.getText() == null) {

if (!tf.getText().equals("") {

但异常仍然存在。当我删除时:

tf.clear();

一切正常。

...有什么想法吗?

编辑 swinkler 的解决方案:

我在使用 swinkler 的代码时得到的异常来源 - JDK 1.8.0_45:

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 com.sun.javafx.scene.control.skin.TextFieldSkin.replaceText(TextFieldSkin.java:576)
    at com.sun.javafx.scene.control.behavior.TextFieldBehavior.replaceText(TextFieldBehavior.java:202)
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.defaultKeyTyped(TextInputControlBehavior.java:238)
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(TextInputControlBehavior.java:139)
    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$91/476337053.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.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$142/181559839.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/2117255219.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)

【问题讨论】:

  • 似乎您正在为文本字段的 textProperty() 更改时添加一个侦听器。如果您想在处理事件时更改文本应该包含的内容,您应该使用new value 参数而不是使用clear()
  • 我喜欢在字符串与模式匹配后让文本字段为新输入做好准备。我也尝试使用 tf.settext("") 而不是 tf.clear()。它也给出了同样的例外。
  • 重点是,您不应该尝试修改字段中的文本,因为您正在处理text modified 事件。我认为正确的方法是将参数newValue设置为“”。
  • 好的,谢谢,我明白了。但我不知道如何正确地做到这一点。当我将侦听器部分中的 newValue 设置为“”时,它不会清除文本字段。当我将被调用函数中的 String 设置为 "" 时,它没有任何效果。我的意图是在值匹配时不使用按钮或额外键从文本字段中获取值。也许你还有其他的想法如何处理它?

标签: java regex exception listener textfield


【解决方案1】:

我有同样的problem,发现了错误报告JDK-8081700,解决了这个问题。事实证明这不是一个错误。

测试用例尝试修改更改内部的文本属性 处理程序。这不受支持,并且属性事件处理程序是 不重入。

正确的做法是让应用延迟修改, 使用 runLater():

    if (matcher.find()) { 
        System.err.println("true"); 
        Platform.runLater(() -> { 
            textField.clear(); 
        }); 
    }

【讨论】:

    【解决方案2】:

    在简单的 JavaFX 应用程序中使用它时,我无法得到您的错误。这是我用来测试您的实现的代码。我的测试输入是“AA20552055T”以匹配正则表达式 - 文本字段被清除。

    您能否与您的解决方案进行比较:

    public class JavaFXApplication1 extends Application {
    
        @Override
        public void start(Stage stage) throws Exception {
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    

    具有您的逻辑的 Controller 类:

    public class FXMLDocumentController implements Initializable {
    
        @FXML
        private TextField textfield;
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            textfield.textProperty().addListener(
                    (observable, oldValue, newValue) -> {
                        handleInput(newValue);
                    });
        }
    
        private void handleInput(String s) {
    
            s = s.toUpperCase();
            Matcher matcher = Pattern
                    .compile(
                            "^[A-Z]{2}(20|21|22|23|[0-1]\\d)[0-5]\\d(20|21|22|23|[0-1]\\d)[0-5]\\d(T\\s|C\\s|TC|CT|\\s\\s)$")
                    .matcher(s);
    
            if (matcher.find()) {
    
                        // do something
                        // then clear the textfield
                textfield.clear();
    
            } else {
                // do something else
            }
        }
    }
    

    FXML 文件:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    
    <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication1.FXMLDocumentController">
        <children>
            <TextField layoutX="126" layoutY="150"  fx:id="textfield" /> 
        </children>
    </AnchorPane>
    

    关于评论,我安装了JDK 1.8.0_45(1.8.0_20之前) 在 Windows 7 x64 上工作 同样,没有错误。

    Here is the jar Netbeans 自动创建 - 我通过 CMD 对其进行了测试。工作也很好。你能测试从 CMD 执行的 jar 文件在你的机器上是否正常工作吗?

    用于调试 - 这是由change 参数给出异常数据的方法。更改有startend

     private void updateContent(TextFormatter.Change change, boolean forceNewUndoRecord) {
            final boolean nonEmptySelection = getSelection().getLength() > 0;
            String oldText = getText(change.start, change.end);
    

    然后开始和结束值触发getText(...)中的异常:

     public String getText(int start, int end) {
            if (start > end) {
                throw new IllegalArgumentException("The start must be <= the end");
            }
    
            if (start < 0
                || end > getLength()) {
                throw new IndexOutOfBoundsException();
            }
    
            return getContent().get(start, end);
        }
    

    【讨论】:

    • 感谢您的示例。我做了一个剪切和粘贴,得到了同样的错误(这次是源,发布在下面。我忘了实现 Initializable ooops - 是时候休息一下了。) - 顺便说一句。我正在使用 JDK 1.8.0_45
    • @VictorRomeo:我添加了一些环境信息。
    • 谢谢 - 我收到你的 .jar 错误 - 截图在这里:up.picr.de/22049687bw.jpg - 有什么想法吗?
    • @VictorRomeo - 看起来像是在尝试重新安装 JDK。
    • 只是这样做了 - 没有变化......奇怪......我在 Windows 8 64Bit 上
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2018-10-27
    • 2018-11-24
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    相关资源
    最近更新 更多