Using a JList component as a cell inside a JTable

JListTableExample.java:

import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class JListTableExample extends JFrame {
 
  public JListTableExample() {
    super( "JList inside JTable Example" );
  
    DefaultTableModel dtm = new DefaultTableModel() {
       // make first cell uneditable
       public boolean isCellEditable(int row, int column)
       {
          return !(column == 0);
       }
    };

    final MyListModel dlm1 = new MyListModel(new Object[] { "value1", "value2", "value3",
                                                            "value4", "value5", "value6" });
    final MyListModel dlm2 = new MyListModel(new Object[] { "value7", "value8", "value9",
                                                            "value10", "value11", "value12" });

    dtm.setDataVector(new Object[][]{ { "JList1", dlm1},
                                      { "JList2", dlm2} },
                      new Object[]{ "String","JList"});
                     
    JTable table = new JTable(dtm);
    table.getColumn("JList").setCellRenderer(new JListRenderer());
    table.getColumn("JList").setCellEditor(new JListEditor());
    table.setRowHeight(80);

    JButton addButton = new JButton("Add an element to List1");
    addButton.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent ae) {
          dlm1.addElement("new value");
       }
    });

    JScrollPane scroll = new JScrollPane(table);
    getContentPane().setLayout(new BorderLayout(10, 10));
    getContentPane().add(BorderLayout.CENTER, scroll);
    getContentPane().add(BorderLayout.SOUTH, addButton);

    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) { 
        System.out.println(dlm1);
        System.out.println(dlm2);
        System.exit(0);
      }
    });
  }
 
  public static void main(String[] args) {
    JListTableExample frame = new JListTableExample();
 
    frame.setSize(400, 250);
    frame.setVisible(true);
  }
}
  
class JListRenderer extends JScrollPane implements TableCellRenderer
{
   JList list;
 
   public JListRenderer() {
      list = new JList();
      list.setSelectionBackground(Color.red);
      getViewport().add(list);
   }
 
   public Component getTableCellRendererComponent(JTable table, Object value,
                                  boolean isSelected, boolean hasFocus,
                                  int row, int column)
   {
      if (isSelected) {
         setForeground(table.getSelectionForeground());
         setBackground(table.getSelectionBackground());
         list.setForeground(table.getSelectionForeground());
         list.setBackground(table.getSelectionBackground());
      } else {
         setForeground(table.getForeground());
         setBackground(table.getBackground());
         list.setForeground(table.getForeground());
         list.setBackground(table.getBackground());
      }
 
      list.setModel((MyListModel) value) ;
      list.setSelectedIndices(((MyListModel) value).getSelectedIndices());

      return this;
   }
}

class JListEditor extends DefaultCellEditor {
   protected JScrollPane scrollpane;
   protected JList list; 
   protected MyListModel mlm;
 
   public JListEditor() {
      super(new JCheckBox());
      scrollpane = new JScrollPane();
      list = new JList();  
//      list.setSelectionForeground(Color.red);
      list.setSelectionBackground(Color.red);
      scrollpane.getViewport().add(list);
   }
 
   public Component getTableCellEditorComponent(JTable table, Object value,
                                   boolean isSelected, int row, int column) {
      list.setModel((MyListModel) value);

      mlm = (MyListModel) value;

      return scrollpane;
   }
 
   public Object getCellEditorValue() {
      mlm.setSelectedIndices(list.getSelectedIndices());
      return mlm;
   }
}


class MyListModel extends DefaultListModel
{
   private int[] selectedIndices;

   public MyListModel(Object[] data) {
      for (int i=0; i<data.length; i++) {
         addElement(data[i]);
      }
   }

   public void setSelectedIndices(int[] selectedIndices) {
      this.selectedIndices = selectedIndices;
   }

   public int[] getSelectedIndices() {
      if (selectedIndices == null) return new int[]{};
      return selectedIndices;
   }
 
   public String toString() {
      StringBuffer sb = new StringBuffer();
      sb.append(super.toString());
      if (selectedIndices != null) {
         sb.append("nSelected:n");
         for (int i=0; i<selectedIndices.length; i++) {
            sb.append(get(selectedIndices[i]) + "n");
         }
      }
      return sb.toString();
   }
}