Hi in my Java swing application I need to show all possible existing entries with same initial characters while user typing in a text field. Lets say user type letter 'A' in a text field which should be a country 'America' and 'Africa' would be suggestions. So that user can select one from the list. Country list resides in my database. I know how to retrieve data from DB. But I don't know how to list them and which components I should use to achieve. Can any one guide me? Or if you can provide an example, that would be great.
-
4America and Africa are not countries...they are continents, like Europe, Asia or Oceania. These are countries beginning by 'A': http://en.wikipedia.org/wiki/List_of_country_name_etymologies#A – Charliemops Aug 31 '11 at 11:20
-
I have the same problem , then i have tried using SwingX but Not working, follow my topic: http://stackoverflow.com/questions/9184350/swingx-a-one-keyword-and-several-suggestions – Marwen Trabelsi Feb 07 '12 at 03:48
4 Answers
You could use the autocomplete package from SwingX. Google for "swingx autocomplete" if you need more real life examples, but the simplest way is creating a JComboBox
and calling
AutoCompleteDecorator.decorate(comboBox);
on it.

- 53,145
- 43
- 157
- 230
-
2That server you link to is down. That's the problem with links in answers. – Tomáš Zato Feb 26 '15 at 10:41
You should try JComboBox as an autosuggest box instead of JTextField. But if you still want it to be done using JTextField then...
- Make a JPanel containing list of suggestion.Initially it will be not visible.
- Whenever user types something search for it and add results to the list in JPanel.
- Show that JPanel at the bottom of textfield in upper layer of frame.
- Implement click event on list so that when ever user clicks on it the text is copied to textfield.

- 58,650
- 30
- 162
- 207
I had a similar problem:
I wanted a Textfield for free entering text, but with the possibility to suggest existing values.
I first found this post, but swingX hasn't allowed to enter text other than the suggested ones. Then I found an other post linking to this page: http://www.jroller.com/santhosh/date/20050620
Some modifications and I changed from directory selection to my own Strings. Might post this here for completion and the help for later searchers:
He made an abstract class AutoCompleter
which handels the events:
// @author Santhosh Kumar T - santhosh@in.fiorano.com
public abstract class AutoCompleter{
JList list = new JList();
JPopupMenu popup = new JPopupMenu();
JTextComponent textComp;
private static final String AUTOCOMPLETER = "AUTOCOMPLETER"; //NOI18N
public AutoCompleter(JTextComponent comp){
textComp = comp;
textComp.putClientProperty(AUTOCOMPLETER, this);
JScrollPane scroll = new JScrollPane(list);
scroll.setBorder(null);
list.setFocusable( false );
scroll.getVerticalScrollBar().setFocusable( false );
scroll.getHorizontalScrollBar().setFocusable( false );
popup.setBorder(BorderFactory.createLineBorder(Color.black));
popup.add(scroll);
if(textComp instanceof JTextField){
textComp.registerKeyboardAction(showAction, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), JComponent.WHEN_FOCUSED);
textComp.getDocument().addDocumentListener(documentListener);
}else
textComp.registerKeyboardAction(showAction, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK), JComponent.WHEN_FOCUSED);
textComp.registerKeyboardAction(upAction, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), JComponent.WHEN_FOCUSED);
textComp.registerKeyboardAction(hidePopupAction, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED);
popup.addPopupMenuListener(new PopupMenuListener(){
public void popupMenuWillBecomeVisible(PopupMenuEvent e){
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e){
textComp.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
}
public void popupMenuCanceled(PopupMenuEvent e){
}
});
list.setRequestFocusEnabled(false);
}
static Action acceptAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
JComponent tf = (JComponent)e.getSource();
AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER);
completer.popup.setVisible(false);
completer.acceptedListItem((String)completer.list.getSelectedValue());
}
};
DocumentListener documentListener = new DocumentListener(){
public void insertUpdate(DocumentEvent e){
showPopup();
}
public void removeUpdate(DocumentEvent e){
showPopup();
}
public void changedUpdate(DocumentEvent e){}
};
private void showPopup(){
popup.setVisible(false);
if(textComp.isEnabled() && updateListData() && list.getModel().getSize()!=0){
if(!(textComp instanceof JTextField))
textComp.getDocument().addDocumentListener(documentListener);
textComp.registerKeyboardAction(acceptAction, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_FOCUSED);
int size = list.getModel().getSize();
list.setVisibleRowCount(size<10 ? size : 10);
int x = 0;
try{
int pos = Math.min(textComp.getCaret().getDot(), textComp.getCaret().getMark());
x = textComp.getUI().modelToView(textComp, pos).x;
} catch(BadLocationException e){
// this should never happen!!!
e.printStackTrace();
}
popup.show(textComp, x, textComp.getHeight());
}else
popup.setVisible(false);
textComp.requestFocus();
}
static Action showAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
JComponent tf = (JComponent)e.getSource();
AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER);
if(tf.isEnabled()){
if(completer.popup.isVisible())
completer.selectNextPossibleValue();
else
completer.showPopup();
}
}
};
static Action upAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
JComponent tf = (JComponent)e.getSource();
AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER);
if(tf.isEnabled()){
if(completer.popup.isVisible())
completer.selectPreviousPossibleValue();
}
}
};
static Action hidePopupAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
JComponent tf = (JComponent)e.getSource();
AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER);
if(tf.isEnabled())
completer.popup.setVisible(false);
}
};
/**
* Selects the next item in the list. It won't change the selection if the
* currently selected item is already the last item.
*/
protected void selectNextPossibleValue(){
int si = list.getSelectedIndex();
if(si < list.getModel().getSize() - 1){
list.setSelectedIndex(si + 1);
list.ensureIndexIsVisible(si + 1);
}
}
/**
* Selects the previous item in the list. It won't change the selection if the
* currently selected item is already the first item.
*/
protected void selectPreviousPossibleValue(){
int si = list.getSelectedIndex();
if(si > 0){
list.setSelectedIndex(si - 1);
list.ensureIndexIsVisible(si - 1);
}
}
// update list model depending on the data in textfield
protected abstract boolean updateListData();
// user has selected some item in the list. update textfield accordingly...
protected abstract void acceptedListItem(String selected);
}
And an Instance to handle the Content of the PopUp:
// @author Santhosh Kumar T - santhosh@in.fiorano.com
public class FileAutoCompleter extends AutoCompleter{
public FileAutoCompleter(JTextComponent comp){
super(comp);
}
protected boolean updateListData(){
String value = textComp.getText();
int index1 = value.lastIndexOf('\\');
int index2 = value.lastIndexOf('/');
int index = Math.max(index1, index2);
if(index==-1)
return false;
String dir = value.substring(0, index+1);
final String prefix = index==value.length()-1 ? null : value.substring(index + 1).toLowerCase();
String[] files = new File(dir).list(new FilenameFilter(){
public boolean accept(File dir, String name){
return prefix!=null ? name.toLowerCase().startsWith(prefix) : true;
}
});
if(files == null){
list.setListData(new String[0]);
return true;
} else{
if(files.length==1 && files[0].equalsIgnoreCase(prefix))
list.setListData(new String[0]);
else
list.setListData(files);
return true;
}
}
protected void acceptedListItem(String selected){
if(selected==null)
return;
String value = textComp.getText();
int index1 = value.lastIndexOf('\\');
int index2 = value.lastIndexOf('/');
int index = Math.max(index1, index2);
if(index==-1)
return;
int prefixlen = textComp.getDocument().getLength()-index-1;
try{
textComp.getDocument().insertString(textComp.getCaretPosition(), selected.substring(prefixlen), null);
} catch(BadLocationException e){
e.printStackTrace();
}
}
}
All is called in the program with
new FileAutoCompleter(yourJTextField);

- 1
- 3