0

I looked through a few posts here but couldn't find an answer to this.

I have successfully added a JComboBox to a Jtable cell. However the selected item is not being "remembered".

More specifically:

1) Select an item from a combo box of row A Step 1

2) Go to select a combo box of row B, but the displayed item in row A disappears (anytime the focus is lost, the row A combo box selection disappears) Step 2

3) Go back to row A, the choice is remembered. Step 3

Just to be clear the information is not being lost. Although the combo box does not visually show what equipment was chosen, the selection is saved. However, I would like users to be able to visually see what they just selected without having to select the row again.

This leads me to believe there must be an error with the custom renderer I have used

Here is the following relevant code.

TableModel (Please note that Level2Area is equivalent to Equipment):

public class PreDefJobPlanDialogDataTable extends CygnusAbstractTableModel{

 private static final long serialVersionUID = 1344977933386754731L;

 static final ColumnData columns[] = {
    new ColumnData( "Sel." , 25, 10000, JLabel.LEFT),
    new ColumnData( "Type", 25, 10000, JLabel.LEFT),
    new ColumnData( "Status", 25,  10000,JLabel.LEFT ),
    new ColumnData( "Title", 100,  10000,JLabel.LEFT ),
    new ColumnData( "Equipment Class", 50, 10000, JLabel.LEFT),
    new ColumnData( "Equipment", 100, 10000, JLabel.LEFT)
};

...

public boolean isCellEditable(int rowIndex, int columnIndex) {
    boolean ret = false;
    if( columnIndex == 0 || columnIndex == 5 ) {
        ret = true;             
    }
    return ret;
}

...

public Object getValueAt(int rowIndex, int columnIndex) {
    Object ret = " ";

    if( rowIndex >= 0 && rowIndex < getRowCount() ) {
        PreDefJobPlan obj = (PreDefJobPlan)modelData.get( rowIndex );
        switch( columnIndex ) {

            case 0: ret = obj.getGroupFlag();
            break;
            case 1: ret = obj.getType();
            break;
            case 2: ret = obj.getStatus();
            break;
            case 3: ret = obj.getTitle();
            break;
            case 4: ret = obj.getLevel1Area();
            break;
            case 5: ret = obj.getLevel2Area();
            break;
            case 9: ret = obj.getPreDefJobPlanID();
            break;
            default: ret = " ";
        }
    }
    return ret;
}

...

public void setValueAt( Object obj, int row, int col ) {
    // get the object
    PreDefJobPlan o = (PreDefJobPlan) this.modelData.get( row );
    switch( col ) {
        case 0:
            o.setGroupFlag((Boolean) obj);
        break;
        case 5:
            o.setLevel2Area((Equipment) obj);
        break;
        default: ;
    }
}

Creating Table:

protected void createTable() {
    PreDefJobPlanDialogDataTable dataModel = new PreDefJobPlanDialogDataTable();
    dataModel.setTimeOffset( 0 );

    this.view.getOrdersTable().setHighlighters(HighlighterFactory.createAlternateStriping());
    this.view.getOrdersTable().setAutoCreateColumnsFromModel( false );
    this.view.getOrdersTable().setModel( dataModel );
    this.view.getOrdersTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    this.view.getOrdersTable().setTransferHandler(new TableRowTransferHandler(this.view.getOrdersTable())); 

  for( int i = 0; i < dataModel.getColumnCount(); i++ ) {   
            if( i== 0 ) {
                ...
            }
            else if (i == 5){

                TableCellRenderer renderer = new ComboCellRenderer(); 
                ca.cygnusconsulting.utilities.ColumnData col = dataModel.getColumn( i );
                JComboBox tableCheckBox = new JComboBox();
                tableCheckBox.setModel( lvl1Model );
                tableCheckBox.setAlignmentX(JComboBox.LEFT_ALIGNMENT);
                tableCheckBox.setBackground(this.view.getOrdersTable().getBackground());
                TableCellEditor editor = new ComboBoxCellEditor(tableCheckBox);
                TableColumnExt column = new TableColumnExt( i, col.getWidth(), renderer, editor );
                column.setMaxWidth(col.getMaxWidth());
                this.view.getOrdersTable().addColumn( column ); 
            }
            else{
                ...
            }
        } 

Renderer:

public class ComboCellRenderer extends JComboBox implements TableCellRenderer {

protected static Border noFocusBorder = new EmptyBorder(1,1,1,1);
protected static Border focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");

 public ComboCellRenderer() {
  super();
  setOpaque(true);

 }

  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
  boolean hasFocus, int row, int column) {

    setBackground(isSelected && !hasFocus ? table.getSelectionBackground() : table.getBackground());
    setForeground(isSelected && !hasFocus ? table.getSelectionForeground() : table.getForeground());
    setFont(table.getFont());
    setSelectedItem(value);

  return this;
  }


}

Does anyone have any reasonable suggestions, or any insight into this?

ballBreaker
  • 722
  • 1
  • 10
  • 29
  • 1
    Possible duplicate of [this question](http://stackoverflow.com/questions/19977908/jcombobox-as-jtable-celleditor-with-overriden-stopcellediting-modifies-wrong-tab). – Hovercraft Full Of Eels Feb 24 '15 at 21:57
  • This [`ComboBoxCellEditor`](http://download.java.net/javadesktop/swinglabs/releases/0.8/docs/api/org/jdesktop/swingx/autocomplete/package-summary.html)? – trashgod Feb 25 '15 at 10:31
  • The values aren't being switched. The combo boxes will remember their selections. The issue pertains to the combo box visually showing what was selected. So no, I don't believe this is a duplicate question. As for trashgod, I'm not sure what you're trying to say. – ballBreaker Feb 25 '15 at 14:21

1 Answers1

2

Normally you should use the default cell renderer to display your cell contents and only show the combobox when editting.

A key concept to understand with JTable cell renderers is that a single cell renderer is generally used to draw all of the cells that contain the same type of data.

If you particularly want a combobox to be used for rendering cells, the reason that your cells are blank is that the custom renderer combobox does not have the items added to it. You should populate the cell renderer combobox with the same values as your cell editor combobox.

Richard Neish
  • 8,414
  • 4
  • 39
  • 69
  • Thanks a ton Richard. Been waiting two months for a solution to this. Ended up creating a constructor that accepted a ComboBoxModel and used it as the model for the renderer. – ballBreaker Apr 29 '15 at 16:07
  • From further testing the way I indicated a solution didn't work exactly as intended. The real solution was to have the Model actually populated within the constructor (instead of having it passed in), I believe this is what Richard originally was referring to. Works like a charm now! – ballBreaker May 04 '15 at 14:41