简体   繁体   中英

How to put different JComboBox in each row of JTable dinamically

I would like to create a JTable in my application. The table will contain two coumns, the first is the name of a software module. The second column needs to contain a JComboBox with the revision numbers of the software module in the first column.

Is it even possible or I need to find another way to do this? (For example: put a button to the cell and choose the revision from a popup window)

Thank you in advance!

Here is one possible implementation to use a DefaultComboBoxModel<Integer> as the table column's data type:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class EditableComboCellEditorTest {
  private JComponent makeUI() {
    String[] columnNames = {"version", "revision"};
    Object[][] data = {
      {"1.7.0", makeModel(76, 79, 80)},
      {"1.8.0", makeModel(91, 92, 101, 102)},
    };
    TableModel model = new DefaultTableModel(data, columnNames) {
      @Override public Class<?> getColumnClass(int column) {
        return column == 1 ? DefaultComboBoxModel.class : String.class;
      }
    };
    JTable table = new JTable(model);
    table.setRowHeight(32);
    table.setAutoCreateRowSorter(true);

    TableColumn col = table.getColumnModel().getColumn(1);
    col.setCellRenderer(new ComboCellRenderer());
    col.setCellEditor(new ComboCellEditor());

    return new JScrollPane(table);
  }
  private static DefaultComboBoxModel<Integer> makeModel(Integer... items) {
    return new DefaultComboBoxModel<Integer>(items) {
      @Override public String toString() {
        return Objects.toString(getSelectedItem(), "");
      }
    };
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new EditableComboCellEditorTest().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class ComboCellRenderer implements TableCellRenderer {
  private final JPanel p = new JPanel(new GridBagLayout());
  private final JComboBox<Integer> cb = new JComboBox<>();
  @Override public Component getTableCellRendererComponent(
    JTable table, Object value, boolean isSelected, boolean hasFocus,
    int row, int column) {
    p.removeAll();
    p.setOpaque(false);
    p.add(cb);
    cb.setEditable(true);
    cb.removeAllItems();
    if (value instanceof DefaultComboBoxModel) {
      DefaultComboBoxModel m = (DefaultComboBoxModel) value;
      Object o = m.getSelectedItem();
      if (o instanceof Integer) {
        cb.addItem((Integer) o);
      }
    }
    return p;
  }
}
//https://java-swing-tips.blogspot.jp/2016/08/use-editable-jcombobox-as.html
class ComboCellEditor extends AbstractCellEditor implements TableCellEditor {
  private final JPanel p = new JPanel(new GridBagLayout());
  private final JComboBox<Integer> cb = new JComboBox<>();
  protected ComboCellEditor() {
    super();
    cb.setEditable(true);
    cb.addActionListener(e -> fireEditingStopped());
    p.add(cb);
    p.setOpaque(false);
  }
  @Override public Component getTableCellEditorComponent(
    JTable table, Object value, boolean isSelected, int row, int column) {
    if (value instanceof ComboBoxModel) {
      @SuppressWarnings("unchecked")
      ComboBoxModel<Integer> m = (ComboBoxModel<Integer>) value;
      cb.setModel(m);
    }
    return p;
  }
  @Override public Object getCellEditorValue() {
    @SuppressWarnings("unchecked")
    DefaultComboBoxModel<Integer> m = (DefaultComboBoxModel<Integer>) cb.getModel();
    if (cb.isEditable()) {
      Object o = cb.getEditor().getItem();
      if (o instanceof Integer && m.getIndexOf((Integer) o) < 0) {
        Integer value = (Integer) o;
        int n = m.getSize();
        Vector<Integer> list = new Vector<>(n + 1);
        for (int i = 0; i < n; i++) {
          list.add(m.getElementAt(i));
        }
        list.add(value);
        Collections.sort(list);
        m = new DefaultComboBoxModel<Integer>(list);
        cb.setModel(m);
        cb.setSelectedIndex(m.getIndexOf(value));
      }
    }
    return m;
  }
}

Override the getCellEditor(...) method to return the combo box:

import java.awt.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.table.*;

public class TableComboBoxByRow extends JPanel
{
    List<String[]> editorData = new ArrayList<String[]>(3);

    public TableComboBoxByRow()
    {
        setLayout( new BorderLayout() );

        // Create the editorData to be used for each row

        editorData.add( new String[]{ "Red", "Blue", "Green" } );
        editorData.add( new String[]{ "Circle", "Square", "Triangle" } );
        editorData.add( new String[]{ "Apple", "Orange", "Banana" } );

        //  Create the table with default data

        Object[][] data =
        {
            {"Color", "Red"},
            {"Shape", "Square"},
            {"Fruit", "Banana"},
            {"Plain", "Text"}
        };
        String[] columnNames = {"Type","Value"};

        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        JTable table = new JTable(model)
        {
            //  Determine editor to be used by row
            public TableCellEditor getCellEditor(int row, int column)
            {
                int modelColumn = convertColumnIndexToModel( column );

                if (modelColumn == 1 && row < 3)
                {
                    JComboBox<String> comboBox1 = new JComboBox<String>( editorData.get(row));
                    return new DefaultCellEditor( comboBox1 );
                }
                else
                    return super.getCellEditor(row, column);
            }
        };

        JScrollPane scrollPane = new JScrollPane( table );
        add( scrollPane );
//      table.getColumnModel().getColumn(1).setCellRenderer(new ComboBoxRenderer2() );
    }
/*
    class ComboBoxRenderer2 extends DefaultTableCellRenderer
    {
        @Override
        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            label.setIcon(UIManager.getIcon("Table.descendingSortIcon"));
            return label;
        }
    }
*/
    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("Table Combo Box by Row");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TableComboBoxByRow() );
        frame.setSize(200, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

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