如何仅在JTable中的特定单元格中设置JComboBox

时间:2016-03-16 07:32:28

标签: java swing jtable jcombobox tablecelleditor

我想在一个假设有一个值列表的单元格中添加一个JComboBox。下面是我的代码,但它在列中的所有单元格中添加了组合框。让我知道我的代码中缺少的是仅在所选单元格上设置组合框。

     public class PropertiesTableModel extends AbstractTableModel{

 //this method is called to set the value of each cell
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Field field= (Field) fieldList.get(rowIndex);

        if(columnIndex==0){
            String dataType=field.getFieldDef().getDataType();
            return PropertiesPanel.getPpIns().getDataTypeIcon(dataType);
        }

        if(columnIndex==1){
            return field.getFieldDef().getfName();
        }
        else if (columnIndex==2){
             if(field.getFieldDef().getListValue().size()>0){
                 return createValueListCombo(field.getFieldDef().getListValue());
             }

            return field.getDefaultValue();
        }
        else{
            return null;
        }
    }

        public JComboBox createValueListCombo(List<Value> valueList){
        TableColumn valColumn = table.getColumnModel().getColumn(2);
        JComboBox comboBox=new JComboBox();

        for (Value val: valueList) {
            comboBox.addItem(val.getDescription());
        }
        comboBox.setSelectedIndex(0);
        valColumn.setCellEditor(new DefaultCellEditor(comboBox));
        return comboBox;
    }
}

2 个答案:

答案 0 :(得分:3)

这很简单,可以用两种方式完成

首先,您的模型应该通知编辑器/表当前单元格具有值列表。

public class PropertiesTableModel extends AbstractTableModel {
     @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        // previous stuff
        if (columnIndex == 2) {
            // return the actually selected value, 
            // not the first value of the list!
            // also the values changed by setValueAt() must be considered.
            return null; // implement it!
        }
    }

    public List<Object> getPossibleValues(int row, int column) {
        // this method should return possible values to select.
        // if cell has no possible values and should be editeb 
        // by a text field this methos should return null
        if (column == 2) {
             Field field= (Field) fieldList.get(rowIndex);
             if (field.getFieldDef().getListValue().size() > 0) {
                 return field.getFieldDef().getListValue();
             }
             return null; // probably something else for non-list values
         }
    }

    public void setValueAt(int row, int column) {
        // you need to store the value chosen by the user
    }
}

1)覆盖public TableCellEditor getCellEditor(int row, int column)

中的方法JTable
public TableCellEditor getCellEditor(int row, int column) {
    PropertiesTableModel model = (PropertiesTableModel) getModel();
    List<Object> values = model.getPossibleValues(row, column);
    if (values != null) {
       return new DefaultCellEditor(new JComboBox(values.toArray()));
    } else {
       return super.getCellEditor(row, column);
    }
}

2)您可以创建一个自定义编辑器,将所有调用委托给依赖于当前编辑的单元格的两个(或更多)编辑器之一。

public class CellEditorMulticaster implements TableCellEditor {
    private DefaultTableCellEditor textEditor;
    private DefaultTableCellEditor currentEditor;

    public CellEditorMulticaster() {
        firstEditor = new DefaultTableCellEditor(new JTextField());
    }

    Component getTableCellEditorComponent(JTable table, Object value,
                                      boolean isSelected,
                                      int row, int column) {
        PropertiesTableModel model = (PropertiesTableModel) table.getModel();
        List<Object> values = model.getPossibleValues(row, column);
        if (values != null) {
            currentEditor = new DefaultCellEditor(new JComboBox(values.toArray()));
        } else {
            currentEditor = textEditor;
        }
        return currentEditor.getTableCellEditorComponent(table, value,
               isSelected, row, column);
    }

    public Object getCellEditorValue() {
        return currentEditor.getCellEditorValue();
    }

    public boolean isCellEditable(EventObject anEvent) {
        JTable table = (JTable) anEvent.getSource;
        int row, col;
        if (anEvent instanceof MouseEvent) {
            MouseEvent evt = (MouseEvent) anEvent;
            row = table.rowAtPoint(evt.getPoint());
            col = table.columnAtPoint(evt.getPoint());
        } else {
            row = table.getSelectedRow();
            col = table.getSelectedColumn();
        }
        PropertiesTableModel model = (PropertiesTableModel) table.getModel();
        List<Object> values = model.getPossibleValues(row, column);
        if (values != null) {
            return true;
        } else {
            return textEditor.isCellEditable(anEvent);
        }
    }

    public boolean shouldSelectCell(EventObject anEvent) {
        return true;
    }

    public boolean stopCellEditing() {
        return currentEditor.stopCellEditing();
    }

    public void  cancelCellEditing() {
        currentEditor.cancelCellEditing();
    }

    // same pattern for another methods (delegate to currentEditor)
}   

答案 1 :(得分:0)

很抱歉,我无法添加评论,但我必须报告一个关于Sergiy答案的问题。

用于步骤1:1)重写JTable中的方法public TableCellEditor getCellEditor(int row,int column)

我每次单击comboBox都发现,此代码将创建一个新的combobox作为新的单元格编辑器。当我点击2-3次作为索引超出长度时,我的代码将崩溃。

我对此完全感到困惑,希望能在这里得到答案。

我的代码是:

@Override
    public TableCellEditor getCellEditor(int row, int column) {
        TableModel model = (TableModel) getModel();
        String[] values = model.getPossibleValues(row, column);
        if (values != null) {
            JComboBox<String> comboBox = new JComboBox<String>(values);
            comboBox.addActionListener((e)->{
                model.setValueAt(row, column, comboBox.getSelectedItem());
            });
            return new DefaultCellEditor(comboBox);
        } else {
            return super.getCellEditor(row, column);            
        }
    }