Java 过滤JComboBox

Java 过滤JComboBox,java,swing,filtering,jcombobox,Java,Swing,Filtering,Jcombobox,在开始的时候,我会说我并没有考虑自动完成combobox,而是在我的combobox中有一个“setFilter(Set)”方法,所以它会显示集合中的内容 我无法达到这种效果,尝试了不同的方法,我认为过滤它显示的内容是视图的责任,所以我不应该扩展ComboBoxModel 这就是我到目前为止的情况(主要包括不起作用的情况): import java.awt.*; 导入java.util.Set; 导入javax.swing.*; 公共类FilteredComboBox扩展了JComboBox{

在开始的时候,我会说我并没有考虑自动完成combobox,而是在我的combobox中有一个“setFilter(Set)”方法,所以它会显示集合中的内容

我无法达到这种效果,尝试了不同的方法,我认为过滤它显示的内容是视图的责任,所以我不应该扩展ComboBoxModel

这就是我到目前为止的情况(主要包括不起作用的情况):

import java.awt.*;
导入java.util.Set;
导入javax.swing.*;
公共类FilteredComboBox扩展了JComboBox{
私有模型实体重构;
私有最终DefaultComboxModel filteredModel=new DefaultComboxModel();
私有设置对象显示;
公共过滤器邮箱(ComboBoxModel){
超级(模型);
this.entireModel=模型;
}
public void setFilter(设置objectsToShow){
if(objectsToShow!=null){
this.objectsToShow=objectsToShow;
filterModel();
}否则{
移除过滤器();
}
}
public void removeFilter(){
objectsToShow=null;
filteredModel.removeAllElements();
super.setModel(entireModel);
}
私有void过滤器模型(){
filteredModel.removeAllElements();
对于(int i=0;i
“我认为视图有责任过滤它显示的内容”-我认为,视图显示它告诉的内容,模型驱动它可以显示的内容,但这就是我

这是我在Java1.3中写的一个想法(带有通用更新),它基本上将代理
ComboBoxModel
包装在另一个
ComboxModel
周围。然后,代理(或
FilterableComboxModel
)决定原始模型中的哪些元素与过滤器匹配,并更新其索引

基本上,它所做的只是在自身和原始模型之间生成一个索引映射,因此它不会复制任何内容或生成对原始数据的新引用

过滤通过一个“filterable”接口进行控制,该接口只传递要检查的元素,并期望得到一个
布尔值
结果作为响应。这使得API非常灵活,因为过滤可以以任何方式进行,而无需以任何方式更改
filterableComboxModel
。这也意味着您可以通过简单地应用一个新的过滤器来更改已使用的过滤器

如果像我通常做的那样,您想向过滤器传递一些值,您需要通过
updateFilter
方法通知模型过滤器已更改……是的,我知道,
ChangeListener
可能是一个更好的主意,但我一直试图保持简单;)

为了灵活性(并维护当前的继承模型),核心API基于
ListModel
,这意味着您也可以将相同的概念用于
JList

可过滤列表模型
import java.util.ArrayList;
导入java.util.List;
导入javax.swing.AbstractListModel;
导入javax.swing.ListModel;
导入javax.swing.event.ListDataEvent;
导入javax.swing.event.ListDataListener;
公共类FilterableListModel扩展AbstractListModel实现ListDataListener{
私有列表模型;
私人列表过滤设备;
专用可过滤过滤器;
公共FilterableListModel(){
lstfilteredicies=新阵列列表(25);
}
公共FilterableListModel(ListModel模型){
这个();
setModel(model);
}
公共FilterableListModel(ListModel模型,IFilterable筛选器){
这个();
setModel(model);
设置过滤器(过滤器);
}
公共void集合模型(ListModel父对象){
if(peer==null | |!peer.equals(parent)){
如果(对等!=null){
fireIntervalRemoved(this,0,peer.getSize()-1);
peer.removeListDataListener(此);
}
同伴=父母;
lstfilteredidicies.clear();
如果(对等!=null){
peer.addListDataListener(此);
}
filterModel(true);
}
}
公共ListModel getModel(){
返回同伴;
}
@凌驾
公共int getSize(){
IFilterable filter=getFilter();
返回筛选器==null?getModel()==null?0:getModel().getSize():lstFilteredIndicies.size();
}
@凌驾
公共E getElementAt(int索引){
IFilterable filter=getFilter();
ListModel=getModel();
E值=null;
if(filter==null
import java.awt.*;
import java.util.Set;

import javax.swing.*;


public class FilteredComboBox extends JComboBox {
    private ComboBoxModel entireModel;
    private final DefaultComboBoxModel filteredModel = new DefaultComboBoxModel();

    private Set objectsToShow;

    public FilteredComboBox(ComboBoxModel model) {
        super(model);
        this.entireModel = model;
    }

    public void setFilter(Set objectsToShow) {
        if (objectsToShow != null) {
            this.objectsToShow = objectsToShow;
            filterModel();
        } else {
            removeFilter();
        }
    }

    public void removeFilter() {
        objectsToShow = null;
        filteredModel.removeAllElements();
        super.setModel(entireModel);
    }

    private void filterModel() {
        filteredModel.removeAllElements();
        for (int i = 0; i < entireModel.getSize(); ++i) {
            Object element = entireModel.getElementAt(i);
            addToFilteredModelIfShouldBeDisplayed(element);
        }

        super.setModel(filteredModel);
    }

    private void addToFilteredModelIfShouldBeDisplayed(Object element) {
        if (objectsToShow.contains(element)) {
            filteredModel.addElement(element);
        }
    }

    @Override
    public void setModel(ComboBoxModel model) {
        entireModel = model;
        super.setModel(entireModel);
        if (objectsToShow != null) {
            filterModel();
        }
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.X_AXIS));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DefaultComboBoxModel model = new DefaultComboBoxModel();

        FilteredComboBox cb = new FilteredComboBox(model);
        cb.setPrototypeDisplayValue("XXXXXXXXXXXX");

        f.add(cb);
        f.pack();

        Set objectsToShow = new HashSet();
        objectsToShow.add("1");
        objectsToShow.add("3");
        objectsToShow.add("4");

        cb.setFilter(objectsToShow); // if you set that filter after addElements it will work
        model.addElement("1");
        model.addElement("2");
        model.addElement("3");
        model.addElement("4");
        model.addElement("5");

        f.setVisible(true);
    }
}
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

public class FilterableListModel<E> extends AbstractListModel<E> implements ListDataListener {

    private ListModel<E> peer;
    private List<Integer> lstFilteredIndicies;
    private IFilterable filter;

    public FilterableListModel() {
        lstFilteredIndicies = new ArrayList<Integer>(25);
    }

    public FilterableListModel(ListModel<E> model) {
        this();
        setModel(model);
    }

    public FilterableListModel(ListModel<E> model, IFilterable filter) {
        this();

        setModel(model);
        setFilter(filter);
    }

    public void setModel(ListModel<E> parent) {
        if (peer == null || !peer.equals(parent)) {
            if (peer != null) {
                fireIntervalRemoved(this, 0, peer.getSize() - 1);
                peer.removeListDataListener(this);
            }

            peer = parent;
            lstFilteredIndicies.clear();
            if (peer != null) {
                peer.addListDataListener(this);
            }
            filterModel(true);
        }
    }

    public ListModel<E> getModel() {
        return peer;
    }

    @Override
    public int getSize() {
        IFilterable filter = getFilter();
        return filter == null ? getModel() == null ? 0 : getModel().getSize() : lstFilteredIndicies.size();
    }

    @Override
    public E getElementAt(int index) {
        IFilterable filter = getFilter();
        ListModel<E> model = getModel();

        E value = null;
        if (filter == null) {
            if (model != null) {
                value = model.getElementAt(index);
            }
        } else {
            int filterIndex = lstFilteredIndicies.get(index);
            value = model.getElementAt(filterIndex);
        }
        return value;
    }

    public int indexOf(Object value) {
        int index = -1;
        for (int loop = 0; loop < getSize(); loop++) {
            Object at = getElementAt(loop);
            if (at == value) {
                index = loop;
                break;
            }
        }
        return index;
    }

    @Override
    public void intervalAdded(ListDataEvent e) {
        IFilterable filter = getFilter();
        ListModel model = getModel();

        if (model != null) {
            if (filter != null) {
                int startIndex = Math.min(e.getIndex0(), e.getIndex1());
                int endIndex = Math.max(e.getIndex0(), e.getIndex1());
                for (int index = startIndex; index <= endIndex; index++) {
                    Object value = model.getElementAt(index);
                    if (filter.include(value)) {
                        lstFilteredIndicies.add(index);
                        int modelIndex = lstFilteredIndicies.indexOf(index);
                        fireIntervalAdded(this, modelIndex, modelIndex);
                    }
                }
            } else {
                fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
            }
        }
    }

    @Override
    public void intervalRemoved(ListDataEvent e) {
        IFilterable filter = getFilter();
        ListModel model = getModel();

        if (model != null) {
            if (filter != null) {
                int oldRange = lstFilteredIndicies.size();
                filterModel(false);
                fireIntervalRemoved(this, 0, oldRange);
                if (lstFilteredIndicies.size() > 0) {
                    fireIntervalAdded(this, 0, lstFilteredIndicies.size());
                }
            } else {
                fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
            }
        }
    }

    @Override
    public void contentsChanged(ListDataEvent e) {
        filterModel(true);
    }

    public void setFilter(IFilterable<E> value) {
        if (filter == null || !filter.equals(value)) {
            filter = value;
            if (getModel() != null) {
                if (getModel().getSize() > 0) {
                    fireIntervalRemoved(this, 0, getModel().getSize() - 1);
                }
            }
            filterModel(true);
        }
    }

    public IFilterable<E> getFilter() {
        return filter;
    }

    protected void filterModel(boolean fireEvent) {
        if (getSize() > 0 && fireEvent) {
            fireIntervalRemoved(this, 0, getSize() - 1);
        }
        lstFilteredIndicies.clear();

        IFilterable<E> filter = getFilter();
        ListModel<E> model = getModel();
        if (filter != null && model != null) {
            for (int index = 0; index < model.getSize(); index++) {
                E value = model.getElementAt(index);
                if (filter.include(value)) {
                    lstFilteredIndicies.add(index);
                    if (fireEvent) {
                        fireIntervalAdded(this, getSize() - 1, getSize() - 1);
                    }
                }
            }
        }
    }

    public void updateFilter() {
        IFilterable filter = getFilter();
        ListModel model = getModel();

        if (filter != null && model != null) {
            for (int index = 0; index < model.getSize(); index++) {
                Object value = model.getElementAt(index);
                if (filter.include(value)) {
                    if (!lstFilteredIndicies.contains(index)) {
                        lstFilteredIndicies.add(index);
                        fireIntervalAdded(this, getSize() - 1, getSize() - 1);
                    }
                } else if (lstFilteredIndicies.contains(index)) {
                    int oldIndex = lstFilteredIndicies.indexOf(index);
                    lstFilteredIndicies.remove(oldIndex);
                    fireIntervalRemoved(this, oldIndex, oldIndex);
                }
            }
        }
    }
}
public interface IFilterable<O> {

    public boolean include(O value);

}
import javax.swing.ComboBoxModel;

public class FilterableComboBoxModel<E> extends FilterableListModel<E> implements ComboBoxModel<E> {

    private FilterableComboBoxModel(ComboBoxModel<E> model) {
        super(model);
    }

    public ComboBoxModel<E> getComboBoxModel() {
        return (ComboBoxModel) getModel();
    }

    @Override
    public void setSelectedItem(Object anItem) {
        getComboBoxModel().setSelectedItem(anItem);
    }

    @Override
    public Object getSelectedItem() {
        return getComboBoxModel().getSelectedItem();
    }

}