8

プログラムに JTextField と JList があります。JList には、ユーザーの連絡先が含まれています。JTextField のテキストに基づいて JList をフィルタリングしたいと思います。たとえば、「Mike」と入力すると、「Mike」を含む連絡先のみが表示されます。ユーザーが JTextField をクリアすると、フィルターがリセットされます。

2 つのアレイを使用することで、これを手動で実行できることはわかっています。1 つは元の連絡先用で、もう 1 つはフィルター処理された連絡先用です。ユーザーが JTextField の値を変更すると、元のリストを調べて一時リストを更新し、JList を更新します。手作業を避けるための機能が組み込まれているのではないかと思います。

4

3 に答える 3

18

そのようなことを行う最善の方法は、その内容をフィルタリングする 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 を呼び出す限り、これで十分です。

于 2013-02-07T19:10:00.053 に答える
3

より簡単な解決策はJTable、フィルターと並べ替えの機能が組み込まれている を使用することです ( RowSorter)。単一列のテーブルは、リストと大差ありません。

于 2013-02-07T18:49:40.890 に答える
0

外部ライブラリに問題がなければ、Jide の QuickListFilterField/QuickTreeFilterField をお勧めします。数行のコードで、視覚的にフィルタリング可能な JList/JTree、大文字と小文字を区別する/区別しない検索、ワイルドカード/正規表現の一致などを取得できます。驚くほど使いやすいです。

于 2015-06-30T08:24:02.073 に答える