如何在JTable的每一行中使用不同的JComboBox

时间:2016-09-27 05:58:09

标签: java swing jtable jcombobox

我想在我的应用程序中创建一个JTable。 该表将包含两个coumns,第一个是软件模块的名称。 第二列需要包含一个JComboBox,其中包含第一列中软件模块的修订号。

是否可能或我需要找到另一种方法来做到这一点? (例如:在单元格中放置一个按钮,然后从弹出窗口中选择修订版本)

提前谢谢!

2 个答案:

答案 0 :(得分:2)

以下是使用DefaultComboBoxModel<Integer>作为表列数据类型的一种可能实现:

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;
  }
}

答案 1 :(得分:0)

重写getCellEditor(...)方法以返回组合框:

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();
            }
        });
    }
}