AutoComplete ComboBox in JavaFX
I found a solution that's working for me:
public class AutoCompleteComboBoxListener<T> implements EventHandler<KeyEvent> {
private ComboBox comboBox;
private StringBuilder sb;
private ObservableList<T> data;
private boolean moveCaretToPos = false;
private int caretPos;
public AutoCompleteComboBoxListener(final ComboBox comboBox) {
this.comboBox = comboBox;
sb = new StringBuilder();
data = comboBox.getItems();
this.comboBox.setEditable(true);
this.comboBox.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
comboBox.hide();
}
});
this.comboBox.setOnKeyReleased(AutoCompleteComboBoxListener.this);
}
@Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP) {
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.DOWN) {
if(!comboBox.isShowing()) {
comboBox.show();
}
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.BACK_SPACE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
} else if(event.getCode() == KeyCode.DELETE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
|| event.isControlDown() || event.getCode() == KeyCode.HOME
|| event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
return;
}
ObservableList list = FXCollections.observableArrayList();
for (int i=0; i<data.size(); i++) {
if(data.get(i).toString().toLowerCase().startsWith(
AutoCompleteComboBoxListener.this.comboBox
.getEditor().getText().toLowerCase())) {
list.add(data.get(i));
}
}
String t = comboBox.getEditor().getText();
comboBox.setItems(list);
comboBox.getEditor().setText(t);
if(!moveCaretToPos) {
caretPos = -1;
}
moveCaret(t.length());
if(!list.isEmpty()) {
comboBox.show();
}
}
private void moveCaret(int textLength) {
if(caretPos == -1) {
comboBox.getEditor().positionCaret(textLength);
} else {
comboBox.getEditor().positionCaret(caretPos);
}
moveCaretToPos = false;
}
}
You can call it with
new AutoCompleteComboBoxListener<>(comboBox);
It's based on this and I customized it to fit my needs.
Feel free to use it and if anybody can improve it, tell me.
JavaFX autocomplete ComboBox drop-down size
This is because the comboBox.hide();
method is not called (the drop-down list is automatically updated on show).
You can improve the listener as:
public class AutoCompleteComboBoxListener<T> implements EventHandler<KeyEvent> {
private ComboBox<T> comboBox;
private ObservableList<T> data;
private boolean moveCaretToPos = false;
private int caretPos;
public AutoCompleteComboBoxListener(final ComboBox<T> comboBox) {
this.comboBox = comboBox;
data = comboBox.getItems();
this.comboBox.setEditable(true);
this.comboBox.setOnKeyReleased(AutoCompleteComboBoxListener.this);
}
@Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP) {
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
} else if(event.getCode() == KeyCode.DOWN) {
if(!comboBox.isShowing())
comboBox.show();
caretPos = -1;
moveCaret(comboBox.getEditor().getText().length());
return;
}
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT
|| event.isControlDown() || event.getCode() == KeyCode.HOME
|| event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
return;
}
comboBox.hide();
if(event.getCode() == KeyCode.BACK_SPACE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
} else if(event.getCode() == KeyCode.DELETE) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
ObservableList<T> list = FXCollections.observableArrayList();
for (int i=0; i<data.size(); i++) {
if(data.get(i).toString().toLowerCase().startsWith(
AutoCompleteComboBoxListener.this.comboBox
.getEditor().getText().toLowerCase())) {
list.add(data.get(i));
}
}
String t = comboBox.getEditor().getText();
comboBox.setItems(list);
comboBox.getEditor().setText(t);
if(!moveCaretToPos) {
caretPos = -1;
}
moveCaret(t.length());
if(!list.isEmpty()) {
comboBox.show();
}
}
private void moveCaret(int textLength) {
if(caretPos == -1)
comboBox.getEditor().positionCaret(textLength);
else
comboBox.getEditor().positionCaret(caretPos);
moveCaretToPos = false;
}
}
This update will ensure, that the drop-down list will be hidden and re-shown every time the search String
has been changed.
AutoComplete ComboBox in JavaFX without Lambda Expressions
Your IDE should be able to convert back and forth. Below is a sample of using that in Eclipse.
1)
comboBox.getEditor().focusedProperty().addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
if (comboBox.getSelectionModel().getSelectedIndex() < 0) {
comboBox.getEditor().setText(null);
}
}
});
2)
comboBox.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
comboBox.hide();
}
});
Hope that helps.
Related Topics
Parsing Xml with Regex in Java
Building Executable Jar with Maven
How to Create 2 Separate Log Files with One Log4J Config File
Open a Link in Browser with Java Button
Printing Runtime Exec() Outputstream to Console
What Is Difference Between Crudrepository and JPArepository Interfaces in Spring Data JPA
How to Make Java Honor the Dns Caching Timeout
Run Single Test from a Junit Class Using Command-Line
Java 8 Date and Time: Parse Iso 8601 String Without Colon in Offset
Difference in System. Exit(0) , System.Exit(-1), System.Exit(1 ) in Java
Why Do We Need Immutable Class
Convert an Integer to an Array of Digits
Java 1.6: Creating an Array of List<T>
How to Get the Latest Jre/Jdk as a Zip File Rather Than Exe or Msi Installer