Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 5373
  • Last Modified:

JComboBox cell renderer/editor updates other JComboBox in same JTable

I'm stuck. I have a JTable that holds a JComboBox which is populated depending on the value in another cell (plain) in the same row. Everything displays correctly, with the correct values in each combo box. The problem is when I make a selection on a combo box, any previous combo box selections revert to the default state. I know I'm stomping on either my combo box instance or the Vector I'm populating it with in either my cell editor or cell renderer class. I'm also fairly certain I'm implementing too many instances of JComboBox.

Thanks in advance....
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
 
public class ComboBoxTable extends JTable {
    
    public ComboBoxTable(TableModel tm) {
        super(tm);
        tableModel = (ComboBoxOutputTableModel)tm;
    }
    
    ComboBoxOutputTableModel tableModel;
    
    Vector valuesVector = null;
    
    
    public TableCellRenderer getCellRenderer(int row, int column){
        if(column == 1){
            setValuesVector(row,column);
            MyComboBoxRenderer renderer = new MyComboBoxRenderer(valuesVector);
            getColumnModel().getColumn(1).setCellRenderer(renderer);
            return renderer;
        }
        else return super.getCellRenderer(row, column);
    }
 
    public TableCellEditor getCellEditor(int row, int column)
    {       
        if (column == 1){           
            
            MyComboBoxEditor editor = new InegQueueComboBoxEditor(valuesVector);
            return editor;
        }
        else return super.getCellEditor(row, column);
    }
    
    /**
     * Gets the collection from the table model data for the current row and populates 
     * the Vector that will be set to a comboBox with it
     * tableModel.getData() returns Object[int][String[]]
     */
    public void setValuesVector(int row, int column){
        Object[] modelRow = tableModel.getData()[row];   
        this.valuesVector = new Vector((Vector)modelRow[column]);
    }
 
}
 
public class MyComboBoxRenderer implements TableCellRenderer {
   
    public MyComboBoxRenderer(Vector v){
 
    }
 
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        JComboBox comboBox = null;
               
        if(value == null){
            comboBox = new JComboBox();
        }else{
            Vector vector = (value instanceof Vector)?(Vector)value:new Vector();
            comboBox = new EiiComboBox(vector);
            comboBox.setFont(LookAndFeelConstants.getLabelFont());
        }
        if (isSelected) {
            comboBox.setForeground(table.getSelectionForeground());
            comboBox.setBackground(table.getSelectionBackground());
            
        } else {
            comboBox.setForeground(table.getForeground());
            comboBox.setBackground(table.getBackground());
        }
        return comboBox;
    }
    
}
 
 
public class MyComboBoxEditor extends AbstractCellEditor implements TableCellEditor {
 
    private Component comp = null;
    private int r = 0;
    private int c = 0;
   
    public MyComboBoxEditor(Vector items) {
        super();
    }
    
 
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        Component com = null;
        r = row;
        c = column;
        JComboBox comboBox;
        
        if(value == null || value.toString().length() == 0) com = new JTextField("");
        else if(value instanceof Vector){
            comboBox = new JComboBox();
              if(comboBox.getModel().getSize() > 0){
                    // clear it...
                  comboBox.removeAllItems();
              }
              comboBox.setModel(new DefaultComboBoxModel((Vector)value));
              
              comboBox.addItemListener(new ItemListener(){
                public void itemStateChanged(ItemEvent e) {
                
                	//nothing implemented here yet
                }                  
              });
 
              com = comboBox;
              
        }else {
        
            comboBox = new JComboBox();
              if(comboBox.getModel().getSize() > 0){
                    // clear it...
                  comboBox.removeAllItems();
              }
              comboBox.addItem(value);
              com = comboBox;
        }
        comp = com;
        return com;
    }
 
	//inherited
	
    public Object getCellEditorValue() {
        return null;
    }
}

Open in new window

0
jolly_rog
Asked:
jolly_rog
  • 11
  • 8
1 Solution
 
jolly_rogAuthor Commented:
Just to clarify, the value in the other column is a parameter for a sql query, hence the different values for each row's comboBox. It's also persisted in the data object retrieved from the tableModel, but the value is irrelevant to the current problem.
0
 
objectsCommented:
your renderer never sets the selected item, thus it will always be the default
Set the required value in getTableCellRendererComponent()
0
 
jolly_rogAuthor Commented:
In getTableCellRendererComponent()  I have:

if(value == null){
            comboBox = new JComboBox();
        }else{
            Vector vector = (value instanceof Vector)?(Vector)value:new Vector();
            comboBox = new JComboBox(vector);
        }
}

so should I change that to :
int x = the seleceted index; //dig this value out of the ItemEvent?
new JComboBox(vector.elementAt(x));

?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
objectsCommented:
no you need something like:

comboBox.setSelectedItem(value);

or

comboBox.setSelectedIndex(indexOfValueInVector);

0
 
jolly_rogAuthor Commented:
I tried that and when I make a selection on another row's comboBox, the one I just selected goes back to the default. Same problem.
0
 
jolly_rogAuthor Commented:
I thought maybe my problem is that in my table, I'm sending the renderer the Vector associated with the row I've clicked on, so it overwrites what was populating the comboBox in the previously selected row?
So I made this change:

    public Vector getValuesVector(int row, int column){
        Object[] modelRow = tableModel.getData()[row];  
        return new Vector((Vector)modelRow[column]);
   }
///////
MyComboBoxRenderer renderer = new MyComboBoxRenderer( getValuesVector(int row, int column));

But the values are different in the new Vector(which is the only value the renderer knows),so  the selected item doesn't exist the next time the renderer gets called, right?

 So, how do I fix THAT?

0
 
objectsCommented:
You need to actually set the value to something that is in the combos list, it doesn't make sense to set it to something thats not in there.

0
 
jolly_rogAuthor Commented:
That's what I figured.

One idea I have is to create a data structure that I populate with my result set data and then iterate through it and create a new JComboBox for each set, and just pass them into my renderer and editor.

Or, just use the data structure to hold reference to each collection for the comboBoxes.
0
 
objectsCommented:
How does the value get set to something that is not in the combo?

0
 
jolly_rogAuthor Commented:
I'm going to have to come up with a way to iterate through the "master" data from my result and create a new comboBox for each set of data on the fly, then pass them to my renderer and editor. Each combo has it's own value set at that point.
0
 
objectsCommented:
so soes every combo have a different list of options? where are the options coming from?

0
 
jolly_rogAuthor Commented:
Yeah they're all different, because the value in the other column (which comes from another -simpler- query) is a parameter in the query that produces the values for the combo. By the nature of the schema, they all come out with different value sets. Of course, we're talking 1 - n combos with 0-n items in each one.

I'm still trying to come up with a way to persist the different value sets, but it's tough when it's unkonwn how many there might be.

As I think about it, maybe some factory could pop out the vectors that would all be unique instances, but for the renderer to hold reference to the right one is a challenge.

I'm sure the project architect thought this looked real cool when he did it in vizio.
0
 
objectsCommented:
The available values could be stored in the table model. The renderer could then pull all the required values and setup the combo accordingly.

0
 
jolly_rogAuthor Commented:
So you agree with my idea, that the table model could have a factory method to generate the value objects for the renderer?
0
 
objectsCommented:
sounds ok as long as it doesn't take too long to generate them everytime.

0
 
jolly_rogAuthor Commented:
My next cut is going to try to create an editor model that builds a map of editors keyed by the string value of the first column. We'll see how that goes.
0
 
objectsCommented:
sounds like an overkill (and you'll need renerers as well as editors)
all you need is the combo models.

0
 
jolly_rogAuthor Commented:
I gave up. I just changed the design to iterate my data and set a new row with a label and combo for each iteration. Works great, I can persist the selections and it took 30 minutes.

Thanks for your help, anyway.
0
 
jolly_rogAuthor Commented:
This is a really complex task, and tough, if not impossible to implement, so I'm awarding the points based on the help and accuracy as far as it got me before I went with a different design.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 11
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now