javaswingjscrollpanejlistdefaultlistmodel

JList's ListCellRenderer not printing the proper index of the DefaultListModel


I have a JScrollPane panel with JList mediaList. Content of the list is maintained by DefaultListModel. I get new list model after making a query through JDBC (Sqlite 3)

I'm facing an issue where scroll pane doesn't paint new index of the model when size of the newly generated model is greater than the size of the earlier fetched model.

//Code snippet

label.addMouseListener (new MouseAdapter() {
    DefaultListModel<HashMap<String,String>> mediaModel=new DefaultListModel<>();
    mediaModel=mProvider.getNextMenu(paramsCid); // new DefaultListModel

    medialist = new JList(mediaModel);
    medialist.setOpaque(false);         
    medialist.setCellRenderer(new MediaCellRenderer());

    panel = new JScrollPane(medialist);
    panel.setPreferredSize(new Dimension(300,300));
    pane1.setOpaque(true);
});

class MediaCellRenderer implements ListCellRenderer {
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        System.out.println("index: "+index);
        JLabel menuTextLabel = new JLabel(mediaModel.get(index).get("title"));
        return menuTextLabel;
    }
}

Have observed that MediaCellRenderer prints below index when length of mediaModel is 2

index: 0  
index: 1

But, it prints below index when length of mediaModel is 3

index: 0  
index: 1  
index: 0 // it prints 0 instead of 2

Can anyone help in figuring out this issue?


Solution

  • First of all your rendering code is incorrect. You should NOT be creating a new JLabel. The idea of using a renderer is to share the same renderer for all items in the JList. This makes it more efficient. Read the section from the Swing tutorial on Using a Custom Renderer for more information. Note you will need to follow the link to the combo box tutorial for the actual renderer example code.

    But, it prints below index when length of mediaModel is 3

    The problem is you haven't added the new ListModel to the GUI.

    mediaModel=mProvider.getNextMenu(paramsCid);
    medialist = new JList(mediaModel);
    medialist.setOpaque(false);         
    medialist.setCellRenderer(new MediaCellRenderer());
    
    panel = new JScrollPane(medialist);
    panel.setPreferredSize(new Dimension(300,300));
    pane1.setOpaque(true);
    

    The above creates a new JScrollPane, but you haven't added the scrollpane to the frame.

    The better solution is to just update the JList with the new ListModel:

    mediaModel=mProvider.getNextMenu(paramsCid);
    mediaList.setModel( mediaModel );
    //medialist = new JList(mediaModel);
    //medialist.setOpaque(false);         
    //medialist.setCellRenderer(new MediaCellRenderer()); // may need this as well?
    
    //panel = new JScrollPane(medialist);
    //panel.setPreferredSize(new Dimension(300,300));
    //pane1.setOpaque(true);
    

    this will update the existing scroll pane with the new JList.