Ajuda de JTable com ComboBox! Diferente de outros casos por ai

Ai galeera do GUJ! =]

Seguinte, quero que uma coluna de minha JTable seja uma comboBox… ok?
Mass, ou maior problema é o seguinte, para cada Linha da tabela, o conteudo desse combobox muda.

Ex: (Nome e uma coluna da Tabela normal(String) e CArros é a coluna que tem o combobox de conteudo as Strings em parenteses)
Tabela X
Nome Carros
Joao (Gol, Palio, Fusca)
Jose (Uno, Palio)
Maria (Gol, Ferrari, Monza)

Ai que ta meu problema, eu ate conseguir colcoar o COMBOBOX dentro da coluna da JTABLE, ams o conteudo dela, eh o mesmo para todas as linahs da tabela, e eu preciso de um conteudo que seja vbariavel… =/

Vlws galera! Espero ajuda!
Abrass!

/**
  * each row TableCellEditor
  *
  */
public class EachRowEditor implements TableCellEditor {
  protected Hashtable<Integer, TableCellEditor> editors;
  protected TableCellEditor editor, defaultEditor;

  /**
   * Constructs a EachRowEditor.
   * create default editor
   *
   * @see TableCellEditor
   * @see DefaultCellEditor
   */
  public EachRowEditor() {
    editors = new Hashtable<Integer, TableCellEditor>();
    defaultEditor = new DefaultCellEditor(new JTextField());
  }

  /**
   * @param row    table row
   * @param editor table cell editor
   */
  public void add(int row, TableCellEditor editor) {
    editors.put(new Integer(row),editor);
  }
  public void remove(int row) {
	    editors.remove(new Integer(row));
  }
  public void removeAll(){
	  editors.clear();
  }
  
  public Component getTableCellEditorComponent(JTable table,
      Object value, boolean isSelected, int row, int column) {
    editor = (TableCellEditor)editors.get(new Integer(row));
    if (editor == null) {
      editor = defaultEditor;
    }
    
    return editor.getTableCellEditorComponent(table,
             value, isSelected, row, column);
  }

  public Object getCellEditorValue() {
    return editor.getCellEditorValue();
  }
  public boolean stopCellEditing() {
    return editor.stopCellEditing();
  }
  public void cancelCellEditing() {
    editor.cancelCellEditing();
  }
  public boolean isCellEditable(EventObject anEvent) {
	  if( editor == null ) return true;
    return editor.isCellEditable(anEvent);
  }
  public void addCellEditorListener(CellEditorListener l) {
    editor.addCellEditorListener(l);
  }
  public void removeCellEditorListener(CellEditorListener l) {
    editor.removeCellEditorListener(l);
  }
  public boolean shouldSelectCell(EventObject anEvent) {
    return editor.shouldSelectCell(anEvent);
  }
}

Associo a instância da classe acima na coluna da JTable que quero tratar…

  tableColumn.setCellEditor(_rowEditor);

Associo diferentes comboboxes com diferentes conteúdos à linha do model. A variável li_linha representa a linha da JTable.

  DefaultComboBoxModel comboModel = new DefaultComboBoxModel(vetorQualquer);
  JComboBox comboBox = new JComboBox();
  comboBox.setModel(comboModel);
  _rowEditor.add(li_linha, new DefaultCellEditor(comboBox) );

É desse jeito que eu faço, não sei se existe uma forma melhor…

Abraços,

Sannon

Sannon,

Esse codigo eu deveria colocar em que situação? Estou quebrando a cabeca aqui mas nao consigo… Esse _rowEditor é uma instancia de EachRowEditor certo?

DefaultComboBoxModel comboModel = new DefaultComboBoxModel(vetorQualquer);  
JComboBox comboBox = new JComboBox();  
comboBox.setModel(comboModel);  
_rowEditor.add(li_linha, new DefaultCellEditor(comboBox) );  

E sobre o codigo da classe EachRowEditor fiquei meio perdido nela, mas eu me viro aqui e aprendo tudo sobre ela…

Mas de qlqr jeito, brigadão!
Abraço!

Você terá que manipular editor e render na tabela para ter o “efeito” desejado.
Da uma olhada ai, com algumas melhorias você chega lá.

import java.awt.Component;
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class CarrosTable extends JTable
{
    public static void main( String[] args )
    {
        CarrosTable tabela = new CarrosTable();

        tabela.addItems();

        JFrame f = new JFrame();

        JScrollPane scroller = new JScrollPane();

        scroller.getViewport().add( tabela );

        f.getContentPane().add( scroller );

        f.setSize( new Dimension( 400 , 400 ) );

        f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        f.setVisible( true );

        f.setLocationRelativeTo( null );
    }
    
    public String[] nacionais =
    {
        "Gol",
        "Palio",
        "Fusca"
    };
    
    public String[] importados =
    {
        "Audi A4",
        "Mondeo",
        "HondaFit",
        "Peugeot 307"
    };    
    
    private Model model = new Model();
    private ComboCellRender comboRender = new ComboCellRender();
    private ComboCellEditor comboEditor = new ComboCellEditor();
    
    public CarrosTable()
    {
        this.setModel( model );
        TableColumn c0 = getColumnModel().getColumn( 0 );
        setRowHeight( 18 );
        c0.setCellEditor( comboEditor );
        c0.setCellRenderer( comboRender );
        
        comboEditor.addCellEditorListener( new CellEditorListener() {

            public void editingStopped( ChangeEvent e )
            {
                refreshItem();
            }

            public void editingCanceled( ChangeEvent e )
            {
                
            }
        });
    }

    public void refreshItem()
    {
        Carros c = ( Carros ) model.getItem( getSelectedRow() );

        repaint();
    }    
    
    
    public void addItems()
    {
        Carros c1 = new Carros();
        Carros c2 = new Carros();
        
        c1.setName( nacionais );
        c2.setName( importados );
        
        model.addItem( c1 );
        model.addItem( c2 );
    }
    
    public class Model extends AbstractTableModel
    {
        private final static int COL_CARROS = 0;

        private Vector&lt;Carros&gt; items = new Vector();
        
        private String[] COLUMNS =
        {
            "Nome"
        };        
        
        public int getRowCount()
        {
            return items.size();
        }

        public int getColumnCount()
        {
            return COLUMNS.length;
        }

        @Override
        public String getColumnName( int column )
        {
            return COLUMNS[column];
        }        
        
        @Override
        public boolean isCellEditable( int rowIndex , int columnIndex )
        {
            return columnIndex == 0;
        }        
        
        public Object getValueAt( int rowIndex , int columnIndex )
        {
            Object value = null;
            
            Carros carros = ( Carros) getItem( rowIndex );
            
            switch ( columnIndex )
            {
                case COL_CARROS:
                    value = carros;
                    break;
            }
            
            return value;
        }
        
        public Object getItem( int row )
        {
            return items.elementAt( row );
        }        
        
        public void addItem( Carros value )
        {
            items.add( value );
            
            fireTableDataChanged();
        }        
    }
    
    public class ComboCellEditor   
            extends AbstractCellEditor
            implements TableCellEditor
    {

        private JComboBox combo;
        
        public ComboCellEditor()
        {
            combo = new JComboBox();
        }
        
        public Object getCellEditorValue()
        {
            return combo.getSelectedItem();
        }

        public Component getTableCellEditorComponent( JTable table ,
                                                      Object value ,
                                                      boolean isSelected ,
                                                      int row , int column )
        {
            if ( value instanceof Carros )
            {
                Carros c = ( Carros ) value;

                combo.setModel( new DefaultComboBoxModel( c.getName() ) );
            }
            
            return combo;
        }
    }
    
    
    public class Carros
    {
        private String[] name;

        public String[] getName()
        {
            return name;
        }

        public void setName( String[] value )
        {
            this.name = value;
        }
    }       
    
    public class ComboCellRender extends JLabel implements TableCellRenderer
    {

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

                this.setText( comboEditor.getCellEditorValue() != null
                              ? ( String ) comboEditor.getCellEditorValue()
                              : "" );
            }
            
            return this;
        }
        
    }
}

Sim, a _rowEditor é instância da EachRowEditor. A EachRowEditor você não muda nem codifica nada nela, usa ela desse jeito.

Supondo que você esteja carregando a lista de dados da sua JTable, dentro de um loop, o seu contador de linhas iria no lugar da li_linha.

Em uma outra situação, na JTable você tinha na linha 4 um valor na coluna A e quando ele é alterado, muda a combo da coluna B. Quando o valor da coluna A da linha 4 for alterado, você remove a dropdown da coluna B da linha 4 com os dados antigos ( _rowEditor.remove(4) ) e coloca a nova combo com a nova lista de dados.

Se eu não consegui me explicar direito ainda você, você pode procurar no Google por eachroweditor que eu copiei esta classe de um exemplo que achei na net e talvêz lá esteja melhor explicado.

Abraços,

Sannon