-
-
Save floralvikings/10290131 to your computer and use it in GitHub Desktop.
import javafx.beans.value.ChangeListener; | |
import javafx.beans.value.ObservableValue; | |
import javafx.event.ActionEvent; | |
import javafx.event.EventHandler; | |
import javafx.geometry.Side; | |
import javafx.scene.control.ContextMenu; | |
import javafx.scene.control.CustomMenuItem; | |
import javafx.scene.control.Label; | |
import javafx.scene.control.TextField; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.SortedSet; | |
import java.util.TreeSet; | |
/** | |
* This class is a TextField which implements an "autocomplete" functionality, based on a supplied list of entries. | |
* @author Caleb Brinkman | |
*/ | |
public class AutoCompleteTextField extends TextField | |
{ | |
/** The existing autocomplete entries. */ | |
private final SortedSet<String> entries; | |
/** The popup used to select an entry. */ | |
private ContextMenu entriesPopup; | |
/** Construct a new AutoCompleteTextField. */ | |
public AutoCompleteTextField() { | |
super(); | |
entries = new TreeSet<>(); | |
entriesPopup = new ContextMenu(); | |
textProperty().addListener(new ChangeListener<String>() | |
{ | |
@Override | |
public void changed(ObservableValue<? extends String> observableValue, String s, String s2) { | |
if (getText().length() == 0) | |
{ | |
entriesPopup.hide(); | |
} else | |
{ | |
LinkedList<String> searchResult = new LinkedList<>(); | |
searchResult.addAll(entries.subSet(getText(), getText() + Character.MAX_VALUE)); | |
if (entries.size() > 0) | |
{ | |
populatePopup(searchResult); | |
if (!entriesPopup.isShowing()) | |
{ | |
entriesPopup.show(AutoCompleteTextField.this, Side.BOTTOM, 0, 0); | |
} | |
} else | |
{ | |
entriesPopup.hide(); | |
} | |
} | |
} | |
}); | |
focusedProperty().addListener(new ChangeListener<Boolean>() { | |
@Override | |
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean aBoolean2) { | |
entriesPopup.hide(); | |
} | |
}); | |
} | |
/** | |
* Get the existing set of autocomplete entries. | |
* @return The existing autocomplete entries. | |
*/ | |
public SortedSet<String> getEntries() { return entries; } | |
/** | |
* Populate the entry set with the given search results. Display is limited to 10 entries, for performance. | |
* @param searchResult The set of matching strings. | |
*/ | |
private void populatePopup(List<String> searchResult) { | |
List<CustomMenuItem> menuItems = new LinkedList<>(); | |
// If you'd like more entries, modify this line. | |
int maxEntries = 10; | |
int count = Math.min(searchResult.size(), maxEntries); | |
for (int i = 0; i < count; i++) | |
{ | |
final String result = searchResult.get(i); | |
Label entryLabel = new Label(result); | |
CustomMenuItem item = new CustomMenuItem(entryLabel, true); | |
item.setOnAction(new EventHandler<ActionEvent>() | |
{ | |
@Override | |
public void handle(ActionEvent actionEvent) { | |
setText(result); | |
entriesPopup.hide(); | |
} | |
}); | |
menuItems.add(item); | |
} | |
entriesPopup.getItems().clear(); | |
entriesPopup.getItems().addAll(menuItems); | |
} | |
} |
@DaPutzy I wrote this a loooong time ago, so I'm not 100% certain anymore 😝
I believe it hides the AutoComplete popup when the TextField loses focus
Please could you give me an example of how to implement it?
new AutoCompleteTextField().getEntries().addAll(Arrays.asList("AA", "AB", "AC","BCA"));
Change Line 42 to the following and all entries containing a substring of your input will show up in the popup.
final List<String> filteredEntries = entries.stream().filter(e -> e.toLowerCase().contains(getText().toLowerCase())).collect(Collectors.toList()); searchResult.addAll(fitleredEntries)
someone can help me?
Yesterday i created a application with javafx, but i used the FXML, how to add the AutoCompleteTextField on FXML?
I solved my last question.
Sugestion: In the method "change" add "if (getText() != null)".
Prevents the NullPointException
Como implementarla?????????
Hi viniciosarodrigues, please can you paste here a clear example of how you used this class. I m getting an error when affecting "new AutoCompleteTextField().getEntries().addAll(Arrays.asList("AA", "AB", "AC","BCA"));" to a textField.
How can i preselect the first entry of the context menu? so if I press "enter" it automatically uses the first entry.
I tried with:
entriesPopup.getSkin().getNode().lookup(".menu-item").requestFocus();
but i always get NPE from getNode()
works great, thank you so much!
If you want the program to search in the whole String and not only at the start, change the Line:
SearchResult.addAll(entries.subSet(getText(), getText() + Character.MAX_VALUE));
with:
String[] input = entries.toArray(new String[entries.size()]);
for(int i=0;i<input.length;i++){
if(input[i].contains(getText().toUpperCase())){
searchResult.add(input[i]);
}
}
i know its not really efficient to typCast the entries TreeSet to an Array every time, but i don't wanted to change a lot on the Programm.
could you give me an example of how to implement it?
please give me example how to use this class with fxml TextField ?
When I try to implement as suggested above it returns incompatible with the JavaFX TextField. Would know why this is successful for some of us but not others? The declaration is @FXML private TextField tbxSummary; I have also tried @FXML private AutoCompleteTextField tbxSummary; and edited the FXML document accordingly, but the field still doesn't work. I'm sure I'm just missing something simple but not sure exactly what.
I want to trigger function on selecting value from autocompletiontextfield. How we can achieve this?
Beautiful work sir. Thank you for posting it.
Please could you give me an example of how to implement it?
someone can help me?
Yesterday i created a application with javafx, but i used the FXML, how to add the AutoCompleteTextField on FXML?
Am using Jfoenix JFX Text field, how did you add it to your FXML?
Please could you give me an example of how to implement it?
someone can help me?
Yesterday i created a application with javafx, but i used the FXML, how to add the AutoCompleteTextField on FXML?Am using Jfoenix JFX Text field, how did you add it to your FXML?
I did not add it to FXML. I instantiated on the controller.
Please could you give me an example of how to implement it?
someone can help me?
Yesterday i created a application with javafx, but i used the FXML, how to add the AutoCompleteTextField on FXML?Am using Jfoenix JFX Text field, how did you add it to your FXML?
I did not add it to FXML. I instantiated on the controller.
How?
When I try to implement as suggested above it returns incompatible with the JavaFX TextField. Would know why this is successful for some of us but not others? The declaration is @FXML private TextField tbxSummary; I have also tried @FXML private AutoCompleteTextField tbxSummary; and edited the FXML document accordingly, but the field still doesn't work. I'm sure I'm just missing something simple but not sure exactly what.
Did you find any solution?
There is an issue here, when we click on the empty space of the CustomMenuItem its not clickable, its clickable only if we click on the text in the CustomMenuItem. Any solution for this? I cannot use MenuItem only I can use CustomMenuItem because with CustomMenuItem i can highlight the entered text in the textfield, in list of customMenuItem. please suggest me some solution for this.
Works amazing until today, i even used it from a kotlin class,
I implemented it like @EzequielAyzenberg mentioned
Thank you so much. I wasted hours trying to get the Gluon and ControlsFX AutoCompleteTextFields to work to no avail in Maven. This was so much easier.
What exactly does the part:
? :)