【问题标题】:Filtering JList based on JTextField基于 JTextField 过滤 JList
【发布时间】:2013-02-07 18:26:39
【问题描述】:

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

我知道我可以通过拥有两个数组来手动执行此操作。一个用于原始联系人,一个用于过滤后的联系人。当用户更改 JTextField 的值时,我会查看原始列表,更新临时列表并更新 JList。我只是想知道是否有一些内置功能可以避免体力劳动。

【问题讨论】:

  • 在您的情况下,JList 是如何填充的?你使用自定义的 JListModel 吗?
  • 我稍微编辑了原始帖子@AaronKurtzhals。 JList 是使用 Netbeans GUI 构建器创建的,目前“联系人”被硬编码在 GUI 的 JList 中。
  • 基本上你需要一个代理列表模型。该模型将使用原始模型和过滤器值来确定哪些值将出现在代理模型中。代理模型将简单地维护一个索引引用返回到所有满足过滤器要求的值的原始模型
  • JXList([SwingX 项目](swingx.java.net) 的一部分)完全支持过滤/排序,与核心 JTable 的机制相同。此外,它还基本支持将 textField 的输入绑定到在 RowFilter 中使用的模式
  • @kleopatra 显然 JXList 上的过滤器在排序器上,方法 setRowFilter 作为参数(RowFilter 过滤器)

标签: java swing filter jtextfield jlist


【解决方案1】:

执行此类操作的最佳方法是使用过滤其内容的 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);
    }
}

为了使用它,您需要将它设置为您的 JList,然后根据需要调用 setFilter()。 这是一个例子:

    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.
        }
    });

一旦调用 setFilter() 方法,屏幕上的 JList 就会相应地更改其内容。

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

【讨论】:

  • 简单有效!谢谢!
  • 简单有效!谢谢!
  • 简单有效!谢谢!
【解决方案2】:

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

【讨论】:

  • 当我在谷歌上搜索“过滤器JList”时,我想“如果我在前三个点击中找不到任何好的和简单的东西,我会'挂起费用'并使用JTable..”你猜怎么着?这个页面是 3 中的热门(全部在 SO)并为我解决了 - 使用一张桌子。 ;)
  • 复制和粘贴子类并调用 set 过滤器有什么不“简单”的?戒掉多少?
【解决方案3】:

如果你对外部库没问题,我会推荐 Jide 的 QuickListFilterField/QuickTreeFilterField。只需几行代码,您就可以获得可视觉过滤的 JList/JTree、区分大小写/不区分大小写的搜索、通配符/正则表达式匹配等......非常容易使用!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2013-10-22
    • 2013-09-29
    • 1970-01-01
    • 2020-05-20
    相关资源
    最近更新 更多