JavaFX Textfield with listener gives: “java.lang.IllegalArgumentException: The start must be <= the end”

痴心易碎 提交于 2019-11-28 08:35:15
MorrisMJ

I had the same problem and found the bug report JDK-8081700, which solved the problem. It turns out not a bug.

The test case attempts to modify the text property inside the change handler. This is not supported, and the property event handlers are not re-entrant.

The correct way is for the application to delay the modification, using runLater():

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

I cannot get your error when using this in a simple JavaFX application. Here is the code I used to test your implementation. My test input is "AA20552055T " to match the regexp - the textfield gets cleared.

Can you please compare with your solution:

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);
    }

}

The Controller class with your logic:

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
        }
    }
}

The FXML file:

<?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>

Regarding the comment, I installed JDK 1.8.0_45 (before 1.8.0_20) Working on Windows 7 x64 Again, no error.

Here is the jar Netbeans creates automatically - I tested it from CMD. Works also fine. Can you test if the jar file executed from CMD is working fine on your machine?

For debugging - this is the method where the exception data are given by the change parameter. change has a start and end.

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

The start and end values then trigger the exception in 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);
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!