簡體   English   中英

基於JTextField過濾JList

[英]Filtering JList based on JTextField

我的程序中有一個JTextField和一個JList。 JList包含用戶的聯系人。 我想根據JTextField上的文本過濾JList。 例如,如果我輸入“Mike”,它將只顯示包含“Mike”的聯系人。 當用戶清除JTextField時,它將重置過濾器。

我知道我可以通過兩個數組手動完成此操作。 一個用於原始聯系人,另一個用於過濾聯系人。 當用戶更改JTextField的值時,我將使用原始列表,更新臨時列表並更新JList。 我只是想知道是否有一些內置功能可以避免手工勞動。

執行此類操作的最佳方法是使用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就會相應地改變其內容。

或者,您可能希望為Filter實現一個觀察者/可觀察模式,因此您可以重新過濾列表而無需調用方法setFilter()。 您可以稍后進行試驗。 對於第一次迭代,只要每次用戶在JTextField中鍵入內容時調用方法setFilter,它就足夠了。

一個更簡單的解決方案可能是使用JTable ,它具有內置的過濾和排序功能( RowSorter )。 單列表與列表沒有太大區別。

如果你對外部庫有好處,我會推薦Jide的QuickListFilterField / QuickTreeFilterField。 只需幾行代碼,您就可以獲得視覺上可過濾的JList / JTree,區分大小寫/不區分大小寫的搜索,通配符/正則表達式匹配等......非常容易使用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM