Java 基于JTextField的JList过滤

Java 基于JTextField的JList过滤,java,swing,filter,jtextfield,jlist,Java,Swing,Filter,Jtextfield,Jlist,我的程序中有一个JTextField和一个JList。JList包含用户的联系人。我想根据JTextField上的文本过滤JList。例如,如果我输入“Mike”,它将只显示包括“Mike”在内的联系人。当用户清除JTextField时,它将重置过滤器 我知道我可以通过使用两个数组手动完成这项工作。一个用于原始联系人,一个用于过滤联系人。当用户更改JTextField的值时,我会修改原始列表,更新临时列表并更新JList。我只是想知道是否有一些内置功能可以避免人工操作。一个更简单的解决方案可能是

我的程序中有一个JTextField和一个JList。JList包含用户的联系人。我想根据JTextField上的文本过滤JList。例如,如果我输入“Mike”,它将只显示包括“Mike”在内的联系人。当用户清除JTextField时,它将重置过滤器


我知道我可以通过使用两个数组手动完成这项工作。一个用于原始联系人,一个用于过滤联系人。当用户更改JTextField的值时,我会修改原始列表,更新临时列表并更新JList。我只是想知道是否有一些内置功能可以避免人工操作。

一个更简单的解决方案可能是使用
JTable
,它确实具有内置的过滤和排序功能(
RowSorter
)。单列表与列表没有太大区别。

这样做的最佳方法是使用一个过滤其内容的ListModel实现。 我不知道有任何默认的过滤ListModel实现,但这应该不会太难做到。 这里有一个快速而肮脏的解决方案,只是给你一个想法。你可能想给它添加更多的铃铛和口哨

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);
    }
}
调用方法setFilter()后,屏幕上的JList将相应地更改其内容


或者,您可能希望为过滤器实现一个观察者/可观察模式,这样您就可以在不调用方法setFilter()的情况下重新过滤列表。你可以稍后再做实验。对于第一次迭代,只要用户每次在JTextField中键入内容时调用方法setFilter就足够了。

如果您对外部libs没有意见,我建议使用Jide的QuickListFilterField/QuickTreeFilterField。只需几行代码,就可以获得可视的可过滤JList/JTree、区分大小写/不区分大小写的搜索、通配符/正则表达式匹配等。。。非常容易使用

您的案例中如何填充JList?你使用定制的JListModel吗?我在@AaronKurtzhals编辑了一点原始帖子。JList采用Netbeans GUI builder,目前“联系人”在GUI的JList中硬编码。基本上,您需要一个代理列表模型。此模型将使用原始模型和过滤器值来确定哪些值将出现在代理模型中。代理模型只需维护一个索引引用,以返回到满足筛选要求的所有值的原始模型。Sjxlist(SwingX项目的一部分)(SwingX.java.net))完全支持筛选/排序,机制与core JTable相同。此外,它还支持将文本字段的输入绑定到模式,以便在RowFilter@kleopatra显然,JXList上的过滤器为排序器打开了setRowFilter方法作为参数(RowFilterSimple and effective!谢谢!Simple and effective!谢谢!Simple and effective!谢谢!我在Google上搜索时“filter
JList
”我想,“如果我在前三次点击中没有发现任何好的和简单的东西,我会‘挂起费用’并使用一个
JTable
。”猜怎么着?这个页面是这三次点击中最热门的一次(都是如此),并为我解决了这个问题-使用一个表格。;)有什么不容易“关于复制和粘贴子类以及调用集筛选器??戒掉多少?
    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.
        }
    });