Uso de ObjectTableModel e JTextField

16 respostas
P

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?

16 Respostas

ViniGodoy

Poste seu código.

P
private JTable getJTable(){
    	model = new ObjectTableModel<Calculo>(
    	  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;
	}

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

Marky.Vasconcelos

Associe pelo setDefaultRenderer para a Class que voce quer.

P

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.

Ironlynx

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.

P

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:

Ironlynx

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:

P

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?

Ironlynx
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)
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();
    }
}
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:
P

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!

Ironlynx

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.

P

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…

Ironlynx

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:

P
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:
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();  
	    }  
	
}

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

Ironlynx

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:
public Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected, int rowIndex, int vColIndex) {  	  
	        if (isSelected) {  	            
	        } 
	        for(int j=0;j&lt;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;  
	    }  
}
Deve funcionar. :wink: >
P

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

Criado 16 de agosto de 2012
Ultima resposta 27 de set. de 2012
Respostas 16
Participantes 4