У меня была похожая проблема:
Я хотел текстовое поле для свободного ввода текста, но с возможностью предложить существующие значения.
Я впервые нашел этот пост, но swingX не разрешил вводить текст, кроме предложенных.
Тогда я нашел другой пост, ссылающийся на эту страницу:
http://www.jroller.com/santhosh/date/20050620
Некоторые модификации, и я изменил выбор директории на свои собственные строки. Можете опубликовать это здесь для завершения и помощи для последующих поисковиков:
Он создал абстрактный класс AutoCompleter
, который описывает события:
// @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);
}
И экземпляр для обработки содержимого всплывающего окна:
// @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();
}
}
}
Все вызывается в программе с
new FileAutoCompleter(yourJTextField);