简体   繁体   中英

Error using custom renderer to show value in jComboBox

I have researched and attempted to fill a jcombobox dynamically from an arraylist containing Publisher Objects. I have tried to implement a renderer in order to show the Publishers name using the getName() method. The combobox shows the names when the program is run, however, if a new Publisher is then added to the ArrayList, the combobox becomes blank.

Creating Model:

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

}

Creating renderer:

jComboBoxPublisher.setModel(publisherComboModel);
jComboBoxPublisher.setRenderer(new DefaultListCellRenderer() {
    @Override
    public Component getListCellRendererComponent(JList list,
                                           Object value,
                                           int index,
                                           boolean isSelected,
                                           boolean cellHasFocus) {
        Publisher publisher = (Publisher)value;
        if(value!=null)
        {
            value = publisher.getName();
        }
        return super.getListCellRendererComponent(list, value,
            index, isSelected, cellHasFocus);
    }

在添加新发布者之前

添加新的发布者之后

This is not necessarily an answer, but highlights a potential problem

While skimming over your code, I noticed that you combo box model is simply maintaining a reference to the original list. This isn't necessarily a problem, but may result in some unexpected and potentially, unwanted behaviour...

The main problem, is that the combo box model has no idea when the list is changed, therefore it can't tell combo box that it should updated.

Generally, what I would normally do is make a new List of the original list. This means that if the original is updated, it won't cause issues for the model and and combo box.

I would then add mutation functionality to the combo box model so it could be updated, for example...

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

There are several alternatives to this idea. You could create a "general" model, which listed the publishers, but provided event notification to interested parties, so when you added or removed publishers from this model, interested parties, like the combo box model, would be notified and have an opportunity to update themselves and forward appropriate notifications to their interested parties.

Personally, in larger scaled applications, this is my preferred approach.

Another approach would be to provide the combo box model with direct notification...

Thats, you would maintain a reference to the existing list as you are, but the combo box model would have methods that you could call which it could then forward on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM