java - Filtrado de JList basado en JTextField
swing filter (3)
La mejor manera de hacer cosas como esa es tener una implementación de ListModel que filtre sus contenidos. No sé de ninguna implementación de filtrado de ListModel predeterminada, pero no debería ser demasiado difícil de hacer. Aquí hay una solución rápida y sucia para hacerte una idea. Es posible que desee agregarle más campanas y silbatos.
package test;
import java.util.ArrayList;
import javax.swing.AbstractListModel;
import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
public class FilteredListModel extends AbstractListModel {
public static interface Filter {
boolean accept(Object element);
}
private final ListModel _source;
private Filter _filter;
private final ArrayList<Integer> _indices = new ArrayList<Integer>();
public FilteredListModel(ListModel source) {
if (source == null)
throw new IllegalArgumentException("Source is null");
_source = source;
_source.addListDataListener(new ListDataListener() {
public void intervalRemoved(ListDataEvent e) {
doFilter();
}
public void intervalAdded(ListDataEvent e) {
doFilter();
}
public void contentsChanged(ListDataEvent e) {
doFilter();
}
});
}
public void setFilter(Filter f) {
_filter = f;
doFilter();
}
private void doFilter() {
_indices.clear();
Filter f = _filter;
if (f != null) {
int count = _source.getSize();
for (int i = 0; i < count; i++) {
Object element = _source.getElementAt(i);
if (f.accept(element)) {
_indices.add(i);
}
}
fireContentsChanged(this, 0, getSize() - 1);
}
}
public int getSize() {
return (_filter != null) ? _indices.size() : _source.getSize();
}
public Object getElementAt(int index) {
return (_filter != null) ? _source.getElementAt(_indices.get(index)) : _source.getElementAt(index);
}
}
Para usarlo, debe configurarlo en su JList y luego llamar a setFilter () como lo necesite. Aquí hay un ejemplo:
ListModel source = new DefaultListModel(); // use a model of your choice here;
FilteredListModel filteredListModel = new FilteredListModel(source);
JList list = new JList(filteredListModel);
filteredListModel.setFilter(new FilteredListModel.Filter() {
public boolean accept(Object element) {
return false; // put your filtering logic here.
}
});
Una vez que se invoca el método setFilter (), se espera que su JList en la pantalla cambie su contenido en consecuencia.
Alternativamente, puede implementar un patrón observador / observable para su Filtro, de modo que pueda volver a filtrar la lista sin llamar al método setFilter (). Puedes experimentar con eso más tarde. Para la primera iteración, es lo suficientemente bueno siempre que llame al método setFilter cada vez que el usuario escriba algo en su JTextField.
Tengo un JTextField y una JList en mi programa. La JList contiene los contactos del usuario. Me gustaría filtrar el JList basado en el texto en el JTextField. Por ejemplo, si escribo "Mike", solo se mostrarán los contactos, incluido "Mike". Cuando el usuario borre el JTextField, restablecería el filtro.
Sé que podría hacerlo manualmente teniendo dos matrices. Uno para los contactos originales y otro para los filtrados. Cuando el usuario cambia el valor de JTextField, iré a través de la lista original, actualizaré la lista temporal y actualizaré la JList. Me pregunto si hay alguna característica incorporada para evitar el trabajo manual.
Una solución más simple podría ser usar JTable
, que tiene una capacidad incorporada para filtrar y ordenar ( RowSorter
). Una tabla de columna única no es muy diferente de una lista.
Si está de acuerdo con las librerías externas, recomendaría QuickListFilterField / QuickTreeFilterField de Jide. Con pocas líneas de código, puede obtener una JList / JTree filtrable visualmente, una búsqueda sensible a mayúsculas / minúsculas, una coincidencia de comodines / expresiones regulares, etc. ... ¡Sorprendentemente fácil de usar!