title: Swing JList with custom CellRenderer disappear after adding new element
body: <p>I am coding a JList with checkBoxes using a custom CellRenderer, and a context menu to select/unselect, add or remove an element of the list.</p>
  
  <p>Everything works fine, I can select items, open the context menu and remove/add elements through it. My problem is that when I add an element and there is then more elements in the list than at the beginning, the list disappear and I get a blank panel. This is what happen when adding a new element to the list whithout removing one before, for example.</p>
  
  <p>In order to pinpoint the problem I have been trying to get the code to the minimum but I still don't understand why it doesn't work properly.</p>
  
  <p>What I want to know is why my list goes blank and how can I prevent it from doing so.</p>
  
  <p>Of course, any side-comment or advice is welcome :)</p>
  
  <p>Thanks.</p>
  
  <hr>
  
  <p>Here is the complete code if you want to give it a try (left-click to select items, right-click to open the context menu) :</p>
  
  <p>CheckBoxList.java</p>
  
  <pre><code>package misc;
  
  import javax.swing.*;
  import javax.swing.border.*;
  import java.awt.*;
  import java.awt.event.*;
  
  public class CheckBoxList extends JList {
  
      private int selection = -1;
  
      protected static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
  
      public CheckBoxList(Model m) {
          this();
          this.setModel(m);
      }
  
      public CheckBoxList() {
          this.setCellRenderer(new CheckboxCellRenderer());
          this.addMouseListener(new MouseAdapter() {
  
              @Override
              public void mousePressed(MouseEvent e) {
                  int index = locationToIndex(e.getPoint());
                  selection = index;
                  CheckBoxList cbl = (CheckBoxList) e.getSource();
                  cbl.setSelectedIndex(index);
                  if(index != -1) {
                      if(e.getButton() == MouseEvent.BUTTON1) {
                          Data v = (Data) getModel().getElementAt(index);
                          v.setSelected(!v.isSelected());
                          JCheckBox checkbox = new JCheckBox(v.getS(), v.isSelected());
                          checkbox.setSelected(!checkbox.isSelected());
                          repaint();
                      } else if(e.getButton() == MouseEvent.BUTTON3) {
                          ContextMenu pum = new ContextMenu(cbl);
                          pum.show(e.getComponent(), e.getX(), e.getY());
                      }
                  }
              }
          });
          this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      }
  
      protected class CheckboxCellRenderer implements ListCellRenderer {
  
          @Override
          public Component getListCellRendererComponent(JList list, Object value, int index,
                  boolean isSelected, boolean cellHasFocus) {
              Data v = (Data) value;
              JCheckBox checkbox = new JCheckBox(v.getS(), v.isSelected());
              checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground());
              checkbox.setBorderPainted(true);
              checkbox.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder")
                      : noFocusBorder);
              return checkbox;
          }
      }
  
      public int getSelection() {
          return this.selection;
      }
  
      public class ContextMenu extends JPopupMenu {
  
          private JMenuItem deleteItem;
          private JMenuItem addItem;
          private CheckBoxList cbl;
  
          public ContextMenu(CheckBoxList cbl) {
              this.cbl = cbl;
              this.deleteItem = new JMenuItem("Delete");
              this.deleteItem.addActionListener(new ActionListener() {
  
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      JMenuItem jmi = (JMenuItem) e.getSource();
                      ContextMenu cm = (ContextMenu) jmi.getParent();
                      Model m = (Model) cm.cbl.getModel();
                      m.remove((Data) m.getElementAt(cm.cbl.getSelection()));
                      cm.cbl.repaint();
                  }
              });
              this.add(deleteItem);
  
              this.addItem = new JMenuItem("Add new");
              this.addItem.addActionListener(new ActionListener() {
  
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      JMenuItem jmi = (JMenuItem) e.getSource();
                      ContextMenu cm = (ContextMenu) jmi.getParent();
                      ((Model) cm.cbl.getModel()).add(new Data("Added :)"));
                      cm.cbl.repaint();
                  }
              });
              this.add(addItem);
          }
      }
  }
  </code></pre>
  
  <p>Model.java </p>
  
  <pre><code>package misc;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.swing.ListModel;
  import javax.swing.event.ListDataListener;
  
  public class Model implements ListModel {
  
      private List&lt;Data&gt; data = new ArrayList&lt;Data&gt;();
  
      @Override
      public void addListDataListener(ListDataListener l) {}
  
      @Override
      public Object getElementAt(int index) {
          return data.get(index);
      }
  
      @Override
      public int getSize() {
          return data.size();
      }
  
      @Override
      public void removeListDataListener(ListDataListener l) {}
  
      public void add(Data string) {
          this.data.add(string);
      }
  
      public void remove(Data d) {
          data.remove(d);
      }
  }
  </code></pre>
  
  <p>Data.java</p>
  
  <pre><code>package misc;
  
  public class Data {
  
      private String s;
      private boolean selected = false;
  
      public Data(String s) {
          super();
          this.s = s;
      }
  
      public String getS() {
          return this.s;
      }
  
      public void setS(String s) {
          this.s = s;
      }
  
      public boolean isSelected() {
          return this.selected;
      }
  
      public void setSelected(boolean selected) {
          this.selected = selected;
      }
  
      @Override
      public String toString() {
          return "Data [s=" + this.s + ", isSelected=" + this.selected + "]";
      }
  
  }
  </code></pre>
  
  <p>Main.java</p>
  
  <pre><code>package misc;
  
  import java.awt.Dimension;
  
  import javax.swing.JFrame;
  import javax.swing.JScrollPane;
  
  public class Main {
  
      public static void main(String[] args) {
          JFrame f = new JFrame();
          f.setPreferredSize(new Dimension(500,200));
          f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          Model m = new Model();
          m.add(new Data("test1"));
          m.add(new Data("test2"));
          CheckBoxList cbl = new CheckBoxList(m);
          JScrollPane jsp = new JScrollPane(cbl);
          f.add(jsp);
          f.pack();
          f.setVisible(true);
      }
  }
  </code></pre>