[RESOLVIDO]Ajuda com renderização de célula em formato de moeda em JTable

4 respostas
J

Olá GUJeiros, preciso de um auxilio em uma aplicação simples.
Preciso colocar em uma determinada celula editavel de uma JTable, o formato de moeda.
Sei que muitos condenam o uso de DefaultTableModel, mas a aplicação é simples e todas as tables sao simples, com exceção desta, e estou usando o dafault em todas sem problemas.
O usuario vai digitar um valor e, ao sair ou ao mesmo tempo em que digita, precisa ficar com o formato de moeda.
Em outra aplicação tenho um renderizador para colorir a linha de acordo com o conteudo de uma determinada celula. A logica seria a mesma?
Porém nao sei quais metodos usar deste tipo de renderizador para aplicar ao que preciso.
Já procurei muito, mas nao encontrei quade nada.

Se alguem ja fez isso ou sabe como fazer e puder me dar umas dicas eu agradeço muito.
:thumbup:

4 Respostas

A

Opa,

iae Joni blz cara?

olha só ... em meu sistema aqui eu faço da seguinte maneira ... espero que te ajude...

A classe renderer para a tabela:
class TCRenderer extends DefaultTableCellRenderer {
        
        public TCRenderer () {
            super();
        }
        
        @Override
        public Component getTableCellRendererComponent(javax.swing.JTable table,
                    Object value, boolean isSelected, boolean hasFocus, int row, int column){

            JLabel label = (JLabel)super.getTableCellRendererComponent(
                    table, value, isSelected, hasFocus, row, column);
            
	    //caso queira alinhar os campos da tua tabela	
            if (column == 1) {
                label.setHorizontalAlignment(JLabel.CENTER);
            }
            
            //aqui vc diz ao renderizador como mostrar o valor quando a célula não estiver em edição
            if (column == 1) {
                if (!"".equalsIgnoreCase(label.getText())) 
                    label.setText(String.format("%,.2f", new BigDecimal(label.getText())));
                else 
                    label.setText(String.format("%,.2f", new BigDecimal(0)));
            }
            
	    //aqui vc faz uma visualização de tabela zebrada
            Color cor = Color.BLACK;
            label.setForeground(cor);
            if((row % 2) == 0)
                label.setBackground(Color.WHITE);  
            else 
                label.setBackground(new Color(245, 244, 244));
            
	    //aqui vc coloca um destaque para a celula quando a mesma é selecionada
            if (hasFocus == true){
                label.setBackground(new Color(230, 254, 222));
            }
            
            return label;

        }
        
    }

Agora a classe Editor para tua tabela

class TCEditor extends AbstractCellEditor implements TableCellEditor{

        private JTextField componenteMoeda = new JTextField();
        
        private int coluna;
        String retorno;

        public Component getTableCellEditorComponent(JTable table, Object value,  
                                 boolean isSelected, int row, int column ) { 

            coluna = column;        

            if (value == null){
                if (column == 1) {
                    componenteMedida = Utils.preencheCampoMoeda(componenteMoeda, null);
                } 
            } else {
                if (column == 1) {
	            //esta linha vc configura o campo de moeda na tua tabela
                    componenteMoeda = Utils.preencheCampoMoeda(componenteMoeda, new BigDecimal(value.toString()));
                } 
            }

            //alinhamento
            if (column == 1) {
                componente.setHorizontalAlignment(JLabel.RIGHT);
            } 

            //retorno do campo selecionado para a tabela
            if (column == 1) {
                componenteMoeda.selectAll();
                return componenteMoeda;
            } 

        } 

        public Object getCellEditorValue() {

            if (coluna == 1) {
	        //aqui vc carrega a variavel de retorno para ser usada em sua logica
                retorno = componenteMoeda.getText().replaceAll("\\.", "").replaceAll(",", ".");
		//aqui vc limpa o campo da tabela
                componenteMoeda = Utils.preencheCampoMoeda(componenteMoeda, null);
		//aqui é o retorno do valor inserido
                return retorno;
            } 

        }

	//método para não deixar a célula entrar em modo de edição ao click do mouse
        @Override  
        public boolean isCellEditable(EventObject e) {   
            if (e instanceof MouseEvent)   
                return false;   
            return super.isCellEditable(e);   
        }   

    }

Alguns métodos que irão te ajudar não só com a tabela mas com todos os campos onde vc queira colocar estilo de moeda sendo este um JTextField:

public static JTextField preencheCampoMoeda(final JTextField tfMoeda, BigDecimal valor){
        
        tfMoeda.setDocument(new LimitadorMoeda());
        tfMoeda.setText(Utils.bigDecimalToStringMoeda(valor));
        tfMoeda.setHorizontalAlignment(JTextField.RIGHT);
        
        tfMoeda.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                super.focusGained(e);
                tfMoeda.selectAll();
            }
        });
        
        return tfMoeda;
        
    }

public static String bigDecimalToStringMoeda(BigDecimal valor){
        
        String vl = "0";
        
        if (valor != null){
            valor = valor.setScale(2, BigDecimal.ROUND_HALF_DOWN);
            vl = valor.toString().replaceAll("\\.", "");
        }
        
        return vl;
        
    }
A classe responsável pelo estilo de moeda:
import javax.swing.text.*;

public class LimitadorMoeda extends PlainDocument {   
  
    public static final int maxdigits = 12;   
  
 
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {   
  
        String texto = getText(0, getLength());   
  
        for (int i = 0; i < str.length(); i++) {   
            char c = str.charAt(i);   
            if (!Character.isDigit(c)) {   
                return;   
            }   
        }   
  
        if(texto.length() < LimitadorMoeda.maxdigits){   
            super.remove(0, getLength());   
            texto = texto.replace(".", "").replace(",", "");   
            StringBuffer s = new StringBuffer(texto + str);   
  
            if (s.length() > 0 && s.charAt(0) == '0') {   
                s.deleteCharAt(0);   
            }   
  
            if(s.length() < 3) {   
                if (s.length() < 1) {   
                    s.insert(0,"000");   
                } else if (s.length() < 2) {   
                    s.insert(0,"00");   
                } else {   
                    s.insert(0,"0");   
                }   
            }   
  
            s.insert(s.length()-2, ",");   
  
            if(s.length() > 6) {   
                s.insert(s.length()-6, ".");   
            }   
  
            if(s.length() > 10) {   
                s.insert(s.length()-10, ".");   
            }   
  
            super.insertString(0, s.toString(), a);   
        }   
    }   
  
        @Override  
    public void remove(int offset, int length) throws BadLocationException {   
        super.remove(offset, length);   
        String texto = getText(0, getLength());   
        texto = texto.replace(",", "");   
        texto = texto.replace(".", "");   
        super.remove(0, getLength());   
        insertString(0, texto, null);   
    }   
  
}
Modo de usar na configuração de sua tabela:
TCRenderer tcr = new TCRenderer();
TCEeditor tce = new TCEditor();

TableColumnModel modeloColuna = tabela.getColumnModel();
modeloColuna.getColumn(i).setCellRenderer(tcr);
modeloColuna.getColumn(i).setCellEditor(tce);
Modo de inserir na tabela:
modeloDaSuaTabela.setValueAt(suaVariavelBigDecimal, linha, coluna);
Modo de pegar o valor da tabela:
BigDecimal suaVariavel = new BigDecimal(modeloDaSuaTabela.getValueAt(linha, coluna).toString());

Cara .. eu faço desse jeito ... pode ser que vc encontre uma forma melhor para fazer .. mas dessa forma me atende muito bem
no mas, espero ter te ajudado
Até

J

Olá AlanRS,
estou estudando suas classes e não consegui descobrir a origem das variaveis componenteMedida e componente nos metodos abaixo da classe TCEditor:

<blockquote>if (value == null){

if (column == 1) {

componenteMedida = Utils.preencheCampoMoeda(componenteMoeda, null);

}

} else {

if (column == 1) {

//esta linha vc configura o campo de moeda na tua tabela

componenteMoeda = Utils.preencheCampoMoeda(componenteMoeda, new BigDecimal(value.toString()));

}

}
//alinhamento  
        if (column == 1) {  
            [u]componente[/u].setHorizontalAlignment(JLabel.RIGHT);  
        }  </blockquote>

se puder me ajudar eu agradeço. :thumbup:

J

AlanRS,
com créditos ao root_ neste post : http://www.guj.com.br/java/131563-jtable-no-formato-moeda----problema-com-focus-na-mudanca-de-valores
me pareceu uma solução muito boa, ainda estou testando, mas parece que vai atender a minha necessidade.

Mesmo assim obrigado pela ajuda.

Abraço :lol:

A

Opa, iae Joni,

bom ali é o seguinte … o componente e componenteMedida vc pode trocar para componente moeda, é que na verdade minha TCE esta configurada para trabalhar com vários tipos de componentes e eu quis deixar somente com o exemplo que vc iria precisar…

ainda não vi o link que vc postou do root_ mas essa solução é uma das diversas que existem … no meu caso me atendeu perfeitamente… porém vc tem que analisar qual te atende melhor.

no mas, deixo essa solução para caso vc precise algum dia…

Até

Criado 6 de fevereiro de 2013
Ultima resposta 12 de fev. de 2013
Respostas 4
Participantes 2