Поиск JList в Java

Я пытаюсь создать функцию поиска с помощью JList в Java. У меня есть список контактов в ListModel, который я вставил в JList. Это прекрасно отображает все контакты. Однако у меня есть окно поиска над списком контактов, и я хочу, чтобы контакты были сужены до того, что пользователь вводит в поле поиска по мере ввода (например, поиск Google). Однако, когда я пытаюсь ввести в поле поиска, все контакты исчезают, а затем я также не могу вернуться назад. Мой код KeyListener выглядит следующим образом:

KeyListener klisten = new KeyListener() 
    {
        public void keyPressed(KeyEvent evt) 
        {
            searchResults = new ContactList();
            listModel.removeAllElements();
            searchResults.addContact(contactList.getContact(evt.getKeyChar()));
            for (int i = 0; i < searchResults.getContacts().size(); i++)
            {
                listModel.addElement(searchResults.getContact(i).getFname() + " " + searchResults.getContact(i).getLname());
            }
            contacts = new JList(listModel);
            contacts.validate();
        }
        public void keyReleased(KeyEvent evt) {} 
        public void keyTyped(KeyEvent evt) {}
    };
    searchField.addKeyListener(klisten);

EDIT** исходная ListModel, содержащая все исходные контакты, объявляется перед этим анонимным классом и называется listModel, которую я повторно использовал в этом классе для замены полного списка контактов.

Любая помощь в решении этой проблемы будет очень полезна. Дайте мне знать, если мне нужно опубликовать другие части моего кода.


person vol4life27    schedule 16.08.2012    source источник
comment
Прежде всего, вам действительно не следует использовать для этого KeyListener, вместо этого попробуйте DocumentListener в текстовом поле.   -  person MadProgrammer    schedule 16.08.2012


Ответы (3)


Рассмотрите возможность использования фреймворка, поддерживающего фильтрацию списков, например f.i. SwingX

Затем основные шаги:

  • реализовать RowFilter, который фильтрует контакты на основе фрагментов имен
  • установить DocumentListener в текстовое поле
  • при уведомлении об изменении из документа установить новый фильтр в списке

Фрагмент псевдокода

// the custom RowFilter
public class ContactRowFilter extends RowFilter {
    private String compare;

    public ContactRowFilter(String compare) {
        this.compare = compare;
    }

    public boolean include(Entry entry) {
        Contact contact = (Contact) entry.getValue(0);
        return contact.getName().contains(compare);
    }
}

// custom documentListener
public class SearchFieldListener implements DocumentListener {
    private JXList list;

    public SearchFieldListener(JXList list) {
        this.list = list;
    }

    @Override
    public void insertUpdate(...) {
        updateFilter(evt.getDocument());
    }
    ....
    protected void updateFilter(Document doc) {
        String text = doc.getText(0, doc.getLength());
        list.setRowFilter(text.length > 0 ?
            new ContactRowFilter(text) : null);
    }

}

// usage
JXList list = new JXList(myModel);
list.setAutoCreateRowSorter(true);
DocumentListener listener = new SearchFieldListener(list);
JTextField searchField = new JTextField(20);
searchField.getDocument().addDocumentListener(listener); 
person kleopatra    schedule 16.08.2012

Трудно увидеть логику без остального кода. Рассмотрите возможность публикации SSCCE. Похоже, вы воссоздаете JList в событии ключевого прослушивателя:

contacts = new JList(listModel);

Этот новый список необходимо добавить/прочитать в контейнер. Похоже, что воссоздание списка не требуется, поскольку listModel обновлено, и он должен уведомить список о необходимости обновления изменений, если только searchResults не пуст. Это просто предположение без просмотра кода.

Возможно, будет проще использовать один столбец JTable с поддержкой фильтрации. Дополнительные сведения см. в разделе Сортировка и фильтрация.

person tenorsax    schedule 16.08.2012

Я быстро прочитал и, честно говоря, осталось не так много.

Я не уверен в результате этого метода

searchResults.addContact(contactList.getContact(evt.getKeyChar()));

А это мне подсказывает, что нет доступных контактов

searchResults = new ContactList();

Но это потому, что мне не хватает контекста.

Лучшим решением может быть использование модели «Proxy», в основном модели, которая обертывает модель, которая предоставляет вам функциональность фильтра или, как предложил Макс, JTable

person MadProgrammer    schedule 16.08.2012