Uso de ObjectTableModel e JTextField

Para não usar DefaultTableModel, tô seguindo a dica do Ironlynx, usando o ObjectTableModel do projeto Towell, mas não consigo fazer aparecer nas colunas da minha JTable, um JTextField que eu fiz que formata os números para decimal.Tenho 3 colunas(A,B e Media) que recebem meus JTextField, sendo que as duas primeiras eu posso editar, faço um cálculo com as duas primeiras(usando BigDecimal) e exibo a média na terceira após pressionar um botão.Alguem pode me ajudar?

Poste seu código.

[code]
private JTable getJTable(){
model = new ObjectTableModel(
new AnnotationResolver(Calculo.class), “entrada1,entrada2,Media”);

	if (table == null) {
        table = new JTable();
         table.setModel(model);
         table.setDefaultRenderer(Object.class, new MyCellRenderer());
         TableColumn column1 = table.getColumnModel().getColumn(0);
         column1.setCellEditor(new DefaultCellEditor(new JNumberField()));
         TableColumn column2 = table.getColumnModel().getColumn(1);
         column2.setCellEditor(new DefaultCellEditor(new JNumberField()));
        model.setColEditable(0, true);
        model.setColEditable(1, true);
         List<Calculo> listaC=new CalculoDao().listarCalculos();
        model.setData(listaC);
  btnCalc.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
//  Calculos c = model.getValue(table.getSelectedRow()); e códgos de ação do botão...

     	 table.updateUI();
			 }//fim do método actionperformed do botão de comparação
		    });

  }
	return  table;
}[/code]

testei isoladamente o meu JNumberField e ele funciona OK fora da JTable.Alguma idéia???

Associe pelo setDefaultRenderer para a Class que voce quer.

Associe pelo setDefaultRenderer para a Class que voce quer.

Eu retirei o renderer e exibiu o JTextField com os dados!Mas eu tenho problemas para editar os valores!Sempre recebo uns errros:

java.lang.RuntimeException: java.lang.IllegalArgumentException: Can not set java.math.BigDecimal field com.testes.Calculo.entrada1 to java.lang.String at com.towel.el.handler.FieldHandler.setValue(FieldHandler.java:73) at com.towel.el.FieldResolver.setValue(FieldResolver.java:91) at com.towel.swing.table.ObjectTableModel.setValueAt(ObjectTableModel.java:142)

Como eu resolvo isso se para editar eu tenho sempre que ter uma string?Obrigado pela atenção.

PaulH,
vc DEVE fazer o que o marky falou.Lembre-se que vc edita uma String mas faz operações com o BigDecimal.Basicamente, BigDecimal->String(manipula)->BigDecimal(faz operações/cálculos)->String(exibe), e assim sucessivamente.

Ironlynx,

não entendi.Eu tenho que botar a BigDecimal no renderer é isso?Eu sei que quando eu manipulo o textfield só posso fazer como String, mas vem da base como Decimal(como é salvo no BD), vai para BigDecimal, de BD para o JTextField, vai para BD para executar os calculos e volta para String para exibir.OK, eu entendi a teoria, mas não a prática…pode explicar com código, por favor? :oops:

PaulH,
leia esse tópico:
http://www.guj.com.br/java/277369-jtable-com-celulas-jtextfield

Preste muita atenção nos passos descritos pelo ViniGodoy.É o que vc precisa. :wink:

Eu não entendi bem… eu faço o editor da JTable recebendo o meu JtextField, mas como eu faço isso se meu JTextField recebe parâmetros para ter o tamanho do numero e a quantidade de decimais?E eu passo BigDecimal.class para o setDefaultEditor???Eu uso o ObjectTableModel, não dará problema?

PaulH,
não tem mistério, mesmo com o ObjectTableModel!
adicione seu editor:

 TableColumn col = table.getColumnModel().getColumn(suaColunaIndex);
col.setCellEditor(new MyTableCellEditor());

Vc usa um JtextField personalizado, certo?
Vamos pegar esse aqui do Dyorgio nesse tópico:
http://www.guj.com.br/java/272708-mascara-para-jtextfield-valor-real

seu TableCellEditor(daqui: http://www.exampledepot.com/egs/javax.swing.table/CustEdit.html)

[code]
public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
// This is the component that will handle the editing of the cell value
JComponent component = new JNumberFormatField();

// This method is called when a cell value is edited by the user.
public Component getTableCellEditorComponent(JTable table, Object value,
        boolean isSelected, int rowIndex, int vColIndex) {
    // 'value' is value contained in the cell located at (rowIndex, vColIndex)

    if (isSelected) {
        // cell (and perhaps other cells) are selected
    }
    // Configure the component with the specified value
    ((JTextField)component).setText((String)value);

    // Return the configured component
    return component;
}

// This method is called when editing is completed.
// It must return the new value to be stored in the cell.
public Object getCellEditorValue() {
    return ((JTextField)component).getText();
}

}[/code]
Ah!Vc precisa que seu JtextField receba parâmetros para quantidade de casas decimais, certo???
Só mudar o Construtor de MyTableCellEditor. para aceitar um parâmetro inteiro e passe para o
JNumberFormatField que já tem até um construtor para isso!Não testei nada, apenas li o que estava nos links, mas não tem mistério.Testa aí. :wink:

Cara, QUASE funcionou!
O meu problema é que diferentes registros (linhas da minha JTable) tem diferentes cálculos registrados, como:
1,2 e 1,4
234,911 e 456,789
Sacou?A formatação muda de uma linha para outra(com uma casa decimal e com três).E para piorar, formatando eu perco a capacidade de colorir o menor/maior como eu estava fazendo.Pesquisei no google, mas nunca vi formatação multilinhas na jtable, se tiver uma dica, eu aceito!E obrigado pelo código!

1,2 e 1,4 234,911 e 456,789
Nossa…ferrou pra vc!A formatação é feita Coluna a Coluna.Vc tem linhas com diferentes formatações(e ainda precisa abrir para edição e comparação!).O tratamento célula a célula é muito deficiente na JTable(infelizmente!) :cry:

Talvez manipulando o método getCellRenderer lhe ajude, mas não é garantido.

Nossa que droga, não estou tendo sucesso com o getCellRenderer… :cry:
É muito complicado essa formatação.Pena não ter algo mais fácil…

Preciso de algo parecido com isso para um projetinho aqui.Vou sentar e pensar como fazer, mas não é fácil o fato de ter que ->formatar para JTextfield->Muda para BigDecimal/Double/whatever->executa operações ->formata JtextField de novo para cada célula para ser exibido.Se eu conseguir resolver de uma forma decente eu posto aqu para você. :wink:

Iron, fiz como vc me ensinou, mas só a última formatação fica na coluna TODA!Era para a primeira ficar com duas e a segunda com três casas decimais.
casas, mas só ficam as duas com três casas decimais!
Pego as colunas do model:

TableColumn coluna1 = table.getColumnModel().getColumn(1);
TableColumn coluna2 = table.getColumnModel().getColumn(2);
TableColumn coluna3 = table.getColumnModel().getColumn(3);
     for(int j=0;j<listaC.size();j++){
            	Calculo cadastrado=listaC.get(j);
            coluna1.setCellEditor(new FormatTableCellEditor(cadastrado.getRange(),j));
            coluna2.setCellEditor(new FormatTableCellEditor(cadastrado.getRange(),j));
            coluna3.setCellEditor(new FormatTableCellEditor(cadastrado.getRange(),j));
     }

E o formatador como você me passou:

[code]
public class FormatTableCellEditor extends AbstractCellEditor implements TableCellEditor{
JComponent component =null;
int linha=0;

public FormatTableCellEditor(int range,int row){
	   this.linha=row;
	     if(range==5){
		   component = new JNumberFormatField(new DecimalFormat("#,##0.00000")){{setLimit(11);}};
		   }else if(range==4){
		   component = new JNumberFormatField(new DecimalFormat("#,##0.0000")){{setLimit(10);}};
		   }else if(range==3){
		   component = new JNumberFormatField(new DecimalFormat("#,##0.000")){{setLimit(9);}};
		   }else if(range==2){
		   component = new JNumberFormatField(new DecimalFormat("#,##0.00")){{setLimit(8);}};
		   }else if(range==1){
		   component = new JNumberFormatField(new DecimalFormat("#,##0.0")){{setLimit(8);}};
		   }
	   
   }
  
    // This method is called when a cell value is edited by the user.  
    public Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int rowIndex, int vColIndex) {  
        // 'value' is value contained in the cell located at (rowIndex, vColIndex)  
  
        if (isSelected) {  
           
        }  
        if(linha==rowIndex){//linha selecionada
        // Configure the component with the specified value  
        ((JTextField)component).setText((String)value);  
        }
  
        // Return the configured component  
        return component;  
    }  
  
    // This method is called when editing is completed.  
    // It must return the new value to be stored in the cell.  
    public Object getCellEditorValue() {  
        return ((JTextField)component).getText();  
    }  

}[/code]

Porque só pega o último range e atualiza a coluna toda com esse range???

PaulH,
é fácil o porquê de não funcionar.Voce continua formatando apenas por COLUNA.Para lidar diretamente com a célula, vc precisa lidar diretamente com o método getTableCellEditorComponent() para nele, trabalhar célula a célula.Passe sua lista para o seu CellEditor componente para dentro dele, trabalhar com as células.Ou seja:

instalando nas colunas:

coluna1.setCellEditor(new FormatTableCellEditor(suaLista));  
 coluna2.setCellEditor(new FormatTableCellEditor(suaLista));  
 coluna3.setCellEditor(new FormatTableCellEditor(suaLista)); 

Na sua classe que herda de AbstractCellEditor ponha esse construtor:

public FormatTableCellEditor(List&lt;Calculo&gt; l){ super(); this.lista=l;//não esqueça de declarar sua lista }
E um método para controlar a sua escala, igual ao que vc fazia no construtor mas que lida diretamente com seu JComponent:

public JComponent formatarCampo(int range){ JComponent component=null; if(range==5){ component = new JNumberFormatField(new DecimalFormat("#,##0.00000")){{setLimit(11);}}; }else if(range==4){ component = new JNumberFormatField(new DecimalFormat("#,##0.0000")){{setLimit(10);}}; }else if(range==3){ component = new JNumberFormatField(new DecimalFormat("#,##0.000")){{setLimit(9);}}; }else if(range==2){ component = new JNumberFormatField(new DecimalFormat("#,##0.00")){{setLimit(8);}}; }else if(range==1){ component = new JNumberFormatField(new DecimalFormat("#,##0.0")){{setLimit(8);}}; } return component; }

Depois é só acertar o seu getTableCellEditorComponent para lidar com as células individualmente:

[code]
public Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int rowIndex, int vColIndex) {
if (isSelected) {
}
for(int j=0;j<lista.size();j++){
Calculo cadastrado=lista.get(j);
if(j==rowIndex){//compara com a linha
component= formatarCampo(cadastrado.getRange());
}
}

        ((JTextField)component).setText((String)value);   
      
        return component;  
    }  

} [/code]
Deve funcionar. :wink: >

Cara, muuito obrigado!
Ficou perfeito! :smiley: :smiley: :smiley: