Jonathan
As Manuel said, one of the problems is that setPredicate () will run your changed () method twice since you are changing the combobox model, however the real problem is that combobox overwrites the editor values ββwith any values. Here is an explanation of your symptoms:
If I select an item from the list and then try to delete the last character in the text box, nothing happens.
In this case, the removal of the last char actually occurs, however, the first call to setPredicate () corresponds to one possible element (exactly the same element that you deleted with the last char)), and changes the contents of the list to only one element. This causes a call when combobox restores the value of the editor with the current line combobox.getValue (), creating the illusion that nothing is happening. It also calls the second call to your changed () method, but at this point the editor text has already been changed.
Why does this happen only for the first time, but then never again?
Good question! This happens only once because you change the entire combobox base model once (which, as explained earlier, calls the second call to the changed () method).
So, after the previous scenario happens, if you click the drop-down button (right arrow), you will see that you have only one element left, and if you try to delete one symbol again, you will still have the same element, model (combobox content) has not changed because setPredicate () will still match the same content, so it does not call markInvalid () in the TextInputControl class, because the content has not actually changed, which means not restoring item string again (If you want to see where ekstovoe field actually restored for the first time, see. ComboBoxPopupControl.updateDisplayNode () method JavaFX sources).
If I select an item from the list and then try to delete others than the last, the entire row is deleted.
In your second scenario, nothing matches the first call to setPredicate () (NO elements according to the startWith condition), which removes all int elements in which you delete your current selection and editor line.
TIP. Try it and do it for yourself, switch the breakpoint inside the changed () method to find out how many times it is entered and why (the JavaFX source is needed if you want to monitor ComboBox and its component behavior)
Solution: If you want to continue to use your ChangeListener, you can simply attack the main problem (which is the replacement of the editor after calling setPredicate) by restoring the text in the editor after filtering:
class InputFilter implements ChangeListener<String> { private ComboBox<ComboBoxItem> box; private FilteredList<ComboBoxItem> items; public InputFilter(ComboBox<ComboBoxItem> box, FilteredList<ComboBoxItem> items) { this.box = box; this.items = items; } @Override public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { String value = newValue;
Personally, I have done this before with KeyEvent handlers in the past (to avoid multiple calls to my code in the changed () event), however you can always use Semaphore or your favorite class from java.util.concurrent to avoid unwanted re-entry into your method if you feel that you will come in handy. Right now, getEditor (). SetText () will always return the correct value, even if the same method bubbles two or three times.
Hope this helps!