When writing helper objects for textfields that help tidy up user input, optimal ordering of the events coming from TextInputControl is crucial. The bugs I have found are complex, so let me explain by an example. I am to write a class which helps all users write phone numbers the same way. In our app Danish phone numbers should always start with the country code +45 and have a space for every two numbers. So as users are typing a Danish phone number +4512345678 with no spaces, we listen in on the updates to the text field and change the number to the conventional and much more readable +45 12 34 56 78. I have had several attempts at writing this code, and the reason I have not succeeded is because of the way TextField orders the events occurring.
My first attempt was to listen to the textProperty of TextField using a ChangeListener. As the changes arrived I would insert spaces using textField.insertText(...) and make sure to ignore the additional change events stemming from these additional inserts. I have done something quite similar in Swing, but here in JavaFX this fails, because TextField does not update the caret position until *after* my ChangeListener is invoked, leading to this ordering of things:
1. The user types a number in the TextField
2. Before updating the caretPosition TextField invokes our ChangeListener attached to the textProperty
3. We then change the text ourselves, adding spaces to the phone number by invoking textField.insertText()... (and deliberately ignoring the additional change events coming from that)
4. TextField now updates the caretPosition to the position which would have been correct *before* our insertion of spaces, consequently ignoring the caret updates coming from insertText.
I also tried listening for key typed events, but here the problem is our listener is invoked even before the text of the text field is updated.
I think it is crucial that this is solved. Tidying up user input is a well-known, real world problem, and JavaFX has to support that. I do not know all the inner workings of TextField, but one solution to this issue could be to update the caret position before the ChangeListeners of the textProperty are invoked, so additional caret updates are not overwritten.