Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

JComboBox cell renderer/editor updates other JComboBox in same JTable

Posted on 2008-06-18
19
Medium Priority
?
5,367 Views
Last Modified: 2013-12-14
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
Comment
Question by:jolly_rog
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 8
19 Comments
 

Author Comment

by:jolly_rog
ID: 21817794
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
 
LVL 92

Expert Comment

by:objects
ID: 21818333
your renderer never sets the selected item, thus it will always be the default
Set the required value in getTableCellRendererComponent()
0
 

Author Comment

by:jolly_rog
ID: 21818468
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 92

Expert Comment

by:objects
ID: 21818482
no you need something like:

comboBox.setSelectedItem(value);

or

comboBox.setSelectedIndex(indexOfValueInVector);

0
 

Author Comment

by:jolly_rog
ID: 21822788
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
 

Author Comment

by:jolly_rog
ID: 21823300
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
 
LVL 92

Expert Comment

by:objects
ID: 21827291
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
 

Author Comment

by:jolly_rog
ID: 21827981
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
 
LVL 92

Expert Comment

by:objects
ID: 21828033
How does the value get set to something that is not in the combo?

0
 

Author Comment

by:jolly_rog
ID: 21830520
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
 
LVL 92

Expert Comment

by:objects
ID: 21835147
so soes every combo have a different list of options? where are the options coming from?

0
 

Author Comment

by:jolly_rog
ID: 21835994
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
 
LVL 92

Accepted Solution

by:
objects earned 1500 total points
ID: 21839242
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
 

Author Comment

by:jolly_rog
ID: 21839583
So you agree with my idea, that the table model could have a factory method to generate the value objects for the renderer?
0
 
LVL 92

Expert Comment

by:objects
ID: 21842640
sounds ok as long as it doesn't take too long to generate them everytime.

0
 

Author Comment

by:jolly_rog
ID: 21868812
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
 
LVL 92

Expert Comment

by:objects
ID: 21870276
sounds like an overkill (and you'll need renerers as well as editors)
all you need is the combo models.

0
 

Author Comment

by:jolly_rog
ID: 21902741
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
 

Author Closing Comment

by:jolly_rog
ID: 31468603
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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question