title: How to define actively-updating CellEditor within TableModel
body: <p>I'm creating a <code>TableModel</code> which extends <code>AbstractTableModel</code>. Its contents, though, changes regularly and the number of columns changes depending on the data displayed. Occasionally, I'll need to use a <code>ComboBox</code> to edit the cells in column 2, and occasionally I'll need a <code>ComboBox</code> for cells in column 3. </p>
  
  <p>I know you can set the default renderer of a table by doing <code>table.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(myComboBox));</code></p>
  
  <p>Can I set the <code>CellEditor</code> within my <code>TableModel</code> dynamically, so that the <code>CellEditor</code> is updated when I call <code>table.updateUI()</code>?</p>
  
  <p><strong>Edit</strong>: I'm basically passing my <code>TableModel</code> a big <code>WellCollection</code> data structure that I'm using. At risk of boring you with details, it consists of <code>Wells</code>, which consist of <code>Attributes</code>, which consist of <code>ProposedValues</code>. That's not too important, though. The important part is that I want users to be able to flip through attributes and have different <code>ProposedValues</code> display in the table when they click next (which I previously accomplished with <code>updateUI()</code>).  </p>
  
  <p>Note that an <code>Attribute</code> 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.</p>
  
  <p>Here's my code:</p>
  
  <pre><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);
      }
  }
  </code></pre>