Java 使用自定义渲染器在jComboBox中显示值时出错

Java 使用自定义渲染器在jComboBox中显示值时出错,java,Java,我研究并尝试从包含发布者对象的arraylist动态填充jcombobox。我尝试实现一个渲染器,以便使用getName()方法显示发布者名称。当程序运行时,组合框显示名称,但是,如果将新发布服务器添加到ArrayList中,组合框将变为空白 创建模型: public class PublisherComboBoxModel implements ComboBoxModel{ protected List<Publisher> publishers; public Publish

我研究并尝试从包含发布者对象的arraylist动态填充jcombobox。我尝试实现一个渲染器,以便使用getName()方法显示发布者名称。当程序运行时,组合框显示名称,但是,如果将新发布服务器添加到ArrayList中,组合框将变为空白

创建模型:

public class PublisherComboBoxModel implements ComboBoxModel{

protected List<Publisher> publishers;

public PublisherComboBoxModel(List<Publisher> list) {
    this.listeners = new ArrayList();
    this.publishers = list;
    if(list.size() > 0) {
        selected = list.get(0);
    }     
}

protected Object selected;
@Override
public void setSelectedItem(Object item) {
    this.selected = item;
}
@Override
public Object getSelectedItem() {
    return this.selected;
}

@Override
public Object getElementAt(int index) {
    return publishers.get(index);
}
@Override
public int getSize() {
    return publishers.size();
}

protected List listeners;
@Override
public void addListDataListener(ListDataListener l) {
    listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
    this.listeners.remove(l);
}

}

这不一定是答案,但突出了一个潜在的问题

在浏览代码时,我注意到组合框模型只是维护了对原始列表的引用。这不一定是个问题,但可能会导致一些意外的、潜在的、不想要的行为

主要的问题是,组合框模型不知道列表何时更改,因此它不能告诉组合框它应该更新

一般来说,我通常会做的是在原始列表的基础上创建一个新的
列表。这意味着,如果更新了原始版本,则不会导致模型和组合框出现问题

然后,我会在组合框模型中添加变异功能,以便可以对其进行更新,例如

public class PublisherComboBoxModel extends AbstractListModel implements ComboBoxModel {

    private List<Publisher> publishers;
    private Publisher selectedItem;

    public PublisherComboBoxModel(List<Publisher> publishers) {
        this.publishers = new ArrayList<>(publishers);
    }

    public void addPublisher(Publisher pub) {

        publishers.add(pub);
        fireIntervalAdded(this, publishers.size() - 1, publishers.size() - 1);

    }

    @Override
    public int getSize() {            
        return publishers.size();            
    }

    @Override
    public Object getElementAt(int index) {            
        return publishers.get(index);        
    }

    @Override
    public void setSelectedItem(Object anItem) {            
        selectedItem = (Publisher) anItem;            
    }

    @Override
    public Object getSelectedItem() {
        return selectedItem;
    }
}
公共类PublisherComboxModel扩展AbstractListModel实现ComboxModel{
私人名单出版商;
私人出版商selectedItem;
公共发布者ComboxModel(列出发布者){
this.publisher=新的ArrayList(publisher);
}
public void addPublisher(Publisher-pub){
publisher.add(pub);
fireIntervalAdded(这是publisher.size()-1,publisher.size()-1);
}
@凌驾
public int getSize(){
返回publisher.size();
}
@凌驾
公共对象getElementAt(int索引){
返回publisher.get(索引);
}
@凌驾
public void setSelectedItem(对象anItem){
选择editem=(Publisher)anItem;
}
@凌驾
公共对象getSelectedItem(){
返回selectedItem;
}
}
这个想法有几种替代方案。您可以创建一个“通用”模型,该模型列出了发布者,但向相关方提供了事件通知,因此,当您从该模型中添加或删除发布者时,相关方(如组合框模型),将得到通知,并有机会更新自己,并将适当的通知转发给其相关方

就个人而言,在大规模应用中,这是我首选的方法

另一种方法是为组合框模型提供直接通知


也就是说,您可以保持对现有列表的引用,但是组合框模型将具有您可以调用的方法,然后可以转发这些方法。

当新的
发布者
添加到列表中时,您可以演示这个问题吗…@madhi,我已经编辑了这篇文章来展示这个问题。你有一个可以运行的例子来重现这个问题吗?(我们可以一起玩)
public class PublisherComboBoxModel extends AbstractListModel implements ComboBoxModel {

    private List<Publisher> publishers;
    private Publisher selectedItem;

    public PublisherComboBoxModel(List<Publisher> publishers) {
        this.publishers = new ArrayList<>(publishers);
    }

    public void addPublisher(Publisher pub) {

        publishers.add(pub);
        fireIntervalAdded(this, publishers.size() - 1, publishers.size() - 1);

    }

    @Override
    public int getSize() {            
        return publishers.size();            
    }

    @Override
    public Object getElementAt(int index) {            
        return publishers.get(index);        
    }

    @Override
    public void setSelectedItem(Object anItem) {            
        selectedItem = (Publisher) anItem;            
    }

    @Override
    public Object getSelectedItem() {
        return selectedItem;
    }
}