基于JTextField过滤JList [英] Filtering JList based on JTextField

查看:179
本文介绍了基于JTextField过滤JList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序中有一个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 {
boolean accept(Object element);
}

private final ListModel _source;
私人过滤_filter;
private final ArrayList< Integer> _indices = new ArrayList< Integer>();
$ b $ 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();

过滤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);


$ b $ 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);




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

$ p $ ListModel source = new DefaultListModel(); //在这里使用你选择的模型;
FilteredListModel filteredListModel = new FilteredListModel(source);
JList list = new JList(filteredListModel);
filteredListModel.setFilter(new FilteredListModel.Filter(){
public boolean accept(Object element){
return false; //把过滤逻辑放在这里

});

调用setFilter()方法后,屏幕上的JList将相应地更改其内容。 / p>

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


I have a JTextField and a JList in my program. The JList contains the user's contacts. I'd like to filter the JList based on the text on the JTextField. For example, if I type in "Mike" it will only show contacts including "Mike". When the user clears the JTextField it would reset the filter.

I know I could do this manually by having two arrays. One for the original contacts and one for the filtered ones. When the user changes the value of the JTextField I would go trought the original list, update the temporary list and update the JList. I just wonder if there is some built in feature to avoid manual labour.

解决方案

The best way to do things like that is to have a ListModel implementation that filters its contents. I don't know of any default filtering ListModel implementations, but it should not be too hard to do. Here's a quick and dirty solution just to give you an idea. You might want to add more bells and whistles to it.

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

In order to use it you need to set it to your JList and then call setFilter() as you need. Here's an example:

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

Once method setFilter() is invoked your JList on the screen is expected to change its contents accordingly.

Alternatively, you may want to implement an observer/observable pattern for your Filter, so you can re-filter the list without calling method setFilter(). You can experiment with that later. For the first iteration it's good enough as long as you call method setFilter every time user types something in your JTextField.

这篇关于基于JTextField过滤JList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆