Search code examples
javaswingawtjlistdefaultlistmodel

JscrollPane doesn't update when changing JList model (Java swing)


I have a JList with a custom DefaultListModel. The JList is inside a JScrollPane that is inside a JTabbedPane. When I update the model by adding or removing elements I see no changes on the page even though the model has properly changed.

I tried to revalidate() and repaint() everything and it didn't change.

Now comes the funny thing. If I print every thing in model with a for (int i = 0; i < model.size(); i++) model.get(i) it only shows the modified list. BUT if I go through the list inside my custom model by putting it public, nothing has been changed.

The List I can view updates only if I create and set a new model with another List that I filled manually.

TLDR;

After modifying list in custom DefaultListModel with addElement and removeElement how can this shows the modified list :

for (int i = 0; i < model.size(); i++) {
        System.out.println(model.get(i));
    }

And this shows the original list and the view is therefore not being updated

for (Object object : model.list) {
        System.out.println(object);
    }

My DefaultListModel class

public class ObjectListModel extends DefaultListModel
{
    final List<Object> list;

    public ObjectListModel(List<Object> list) {
        this.list = list;
    }

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

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

Solution

  • This is wrong:

    public class ObjectListModel extends DefaultListModel
    {
        final List<Object> list;  // <===== this here
    

    A DefaultListModel already has a data nucleus that backs the model, and so your list field ignores and tries to override this unsuccessfully.

    Regarding:

    After modifying list in custom DefaultListModel with addElement and removeElement how can this shows the modified list :

    And calling those methods will modify the data nucleus that DefaultListModel holds by default, and will not change your own list field in the least.

    I suggest that you either get rid of the list field and instead pass data to the super object, including its constructor if need be, or else extend AbstractListModel and then sure, use your own data nucleus. If you do use an AbstractListModel-derived class, you must take care to properly call the notification methods when the model changes, something a DefaultListModel takes care of for you.

    To be honest, based on what you're posting, and unless you have requirements not mentioned in your question, I'm not sure that you even need to extend either DefaultListModel or AbstractListModel but rather simply use a DefaultListModel as-is.