0

I'm creating a TableModel which extends AbstractTableModel. Its contents, though, changes regularly and the number of columns changes depending on the data displayed. Occasionally, I'll need to use a ComboBox to edit the cells in column 2, and occasionally I'll need a ComboBox for cells in column 3.

I know you can set the default renderer of a table by doing table.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(myComboBox));

Can I set the CellEditor within my TableModel dynamically, so that the CellEditor is updated when I call table.updateUI()?

Edit: I'm basically passing my TableModel a big WellCollection data structure that I'm using. At risk of boring you with details, it consists of Wells, which consist of Attributes, which consist of ProposedValues. That's not too important, though. The important part is that I want users to be able to flip through attributes and have different ProposedValues display in the table when they click next (which I previously accomplished with updateUI()).

Note that an Attribute can either be an elevation type or not an elevation type. If it is an elevation type, there needs to be an extra column in there.

Here's my code:

public class ProposedValueTableModel extends AbstractTableModel{
    private WellCollection wells;

    public ProposedValueTableModel(WellCollection wells){
        this.wells = wells;
    }


    @Override
    public int getColumnCount() {
        // if we're dealing with elevation values, we want fields for the value, the elevation type,
        // the source, and additional comments. If not, only show value, source, and comments.
        if(wells.getCurrAttribute().isElevationType())
            return 4;
        else return 3;
    }

    @Override
    public int getRowCount() {
        //NOTE: add 1 for extra, blank row! 
        return wells.getCurrAttribute().getProposedValues().size()+1;
    }

    @Override
    public Object getValueAt(int row, int col) {
        //TODO: convert this to handy dandy switch statements
        // make the last row blank to allow entries
        if (row==wells.getCurrAttribute().getProposedValues().size())
            return "";
        ProposedValue propVal = wells.getCurrAttribute().getProposedValues().get(row);
        //if we're NOT dealing with an elevation type, simply have three fields
        if(wells.getCurrAttribute().isElevationType()==false){
            switch(col){
            case 0:
                return propVal.val;
            case 1:
                return propVal.source;
            case 2:
                return propVal.comment;

            }
        }
        // if it IS an elevation value, include elevation type
        else{
            switch(col){
            case 0:
                    return propVal.val;
                case 1:
                    return propVal.elevType;
                case 2:
                    return propVal.source;
                case 3:
                    return propVal.comment;
            }
        }
        return "";
    }

    public String getColumnName(int col){

        if(wells.getCurrAttribute().isElevationType() ==false){
            switch(col){
                case 0:
                    return "Proposed value";
                case 1:
                    return "Source";
                case 2:
                    return "Comment";
            }
        }
        else{
            switch(col){
                case 0:
                    return "Proposed value";
                case 1:
                    return "Type";
                case 2:
                    return "Source";
                case 3:
                    return "Comment";
            }
        }
        return "header";
    }

    public boolean isCellEditable(int row, int col){
        return true;
    }

    public void setValueAt(Object value, int row, int col){
        // we're adding something to the last row, then add a new ProposedValue to the proposedValues array
        if(row == wells.getCurrAttribute().getProposedValues().size()){
            wells.getCurrAttribute().getProposedValues().add(new ProposedValue());
        }
        ProposedValue propVal = wells.getCurrAttribute().getProposedValues().get(row);
        if(wells.getCurrAttribute().isElevationType()==false){
            switch(col){
                case 0:
                    // Value
                    propVal.val = (String)value; break;
                case 1:
                    // Source
                    propVal.source = (String)value; break;
                case 2:
                    // Comment
                    propVal.comment = (String)value; break;
            }
        }
        else{
            switch(col){
                case 0:
                    // Value
                    propVal.val = (String)value; break;
                case 1:
                    // Elevation type
                    propVal.elevType = (String)value; break;
                case 2:
                    // Source
                    propVal.source = (String)value; break;
                case 3:
                    // Comment
                    propVal.comment = (String)value; break;
            }
        }
        //TODO: find out why this is necessary
        fireTableCellUpdated(row, col);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Slothario
  • 2,830
  • 3
  • 31
  • 47

2 Answers2

2

Can I set the CellEditor within my TableModel dynamically, so that the CellEditor is updated when I call table.updateUI()?

  • not, this isn't proper methods for update JTables view

I'm creating a TableModel which extends AbstractTableModel. Its contents, though, changes regularly and the number of columns changes depending on the data displayed. Occasionally, I'll need to use a ComboBox to edit the cells in column 2, and occasionally I'll need a ComboBox for cells in column 3.

Can I set the CellEditor within my TableModel dynamically

  • notice XxxTableModel storing only String value for JComboBox as XxxTableCellEditor

for better help sooner post an SSCCE, short, runnable, compilable, just about JFrame with JTable in JScrollPane with hardcoded value for AbstractTableModel stored as local variable

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • "this isn't proper methods for update JTables view" - explain, please! Also, I pasted my code, but given the complexity of the data structure I'm passing my TableModel, I'm not sure if I could easily make something that would be small and executable to paste here. Should I create a dummy data structure that imitates the functionality of my WellCollection object, so you can see what's going on? – Slothario Apr 08 '13 at 18:12
  • still is there the question if you want to change Items for JComboBox dynamically from outside, or Items could be only different for every JComboBoxes (see answer in this thread by camickr), or JComboBoxes are chained, meaning selection from one JComboBox will to change underlaying ComboBoxModel for another JComboBox ([see linked answer by camickr](http://stackoverflow.com/questions/7109798/how-to-update-2-jcombo-boxs/7110051#7110051)), JComboBox as TableCellEditor has nothing to do with JTable, this is separate JComponent used as editor, last selected value is stored in XxxTableModel – mKorbel Apr 08 '13 at 18:41
2

Can I set the CellEditor within my TableModel dynamically

The CellEditor is not determined by the TableModel.

The JTable determines which editor is used.

You can override the table.getCellEditor(...) method to dynamically change the editor being used. See: https://stackoverflow.com/a/7770309/131872 for an example of this approach.

Community
  • 1
  • 1
camickr
  • 321,443
  • 19
  • 166
  • 288