Campo numérico, Dinheiro, Money, etc... [O RETORNO 2!]

21 respostas
D

Oi pessoal,
com base no sucesso do meu outro tópico (JMoneyField) decidi
colocar um novo campo que pode ser usado como monetario…
esse código é mais maduro e muito mais personalizavel :stuck_out_tongue:
aproveitem, comentem, e melhorem!!!

// Pacote aoqual a classe pertence
package neocode.lib.graphic.field;

// Importa as bibilotecas Java necessárias
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/**
 * Campo para a inserção de números com base em um formato.
 * 
 * @author Dyorgio da Silva Nascimento
 */
public class JNumberFormatField extends JTextField {

  private static final long serialVersionUID = -7506506392528621022L;

  private static final NumberFormat MONETARY_FORMAT = new DecimalFormat("#,##0.00");

  private NumberFormat numberFormat;

  private int limit = -1;

  public JNumberFormatField(int casasDecimais) {
    this(new DecimalFormat((casasDecimais == 0 ? "#,##0" : "#,##0.") + makeZeros(casasDecimais)));
  }

  public JNumberFormatField() {
    this(MONETARY_FORMAT);
  }

  public JNumberFormatField(NumberFormat format) {
    // define o formato do número
    numberFormat = format;
    // alinhamento horizontal para o texto
    setHorizontalAlignment(RIGHT);
    // documento responsável pela formatação do campo
    setDocument(new PlainDocument() {

      private static final long serialVersionUID = 1L;

      @Override
      public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        String text = new StringBuilder(JNumberFormatField.this.getText().replaceAll("[^0-9]", "")).append(
            str.replaceAll("[^0-9]", "")).toString();
        super.remove(0, getLength());
        if (text.isEmpty()) {
          text = "0";
        }else{
          text = new BigInteger(text).toString();
        }

        super.insertString(0, numberFormat.format(new BigDecimal(getLimit() > 0 && text.length() > getLimit() ? text
            .substring(0, getLimit()) : text).divide(new BigDecimal(Math.pow(10, numberFormat
            .getMaximumFractionDigits())))), a);
      }

      @Override
      public void remove(int offs, int len) throws BadLocationException {
        super.remove(offs, len);
        if (len != getLength()) {
          insertString(0, "", null);
        }
      }
    });
    // mantem o cursor no final do campo
    addCaretListener(new CaretListener() {

      boolean update = false;

      @Override
      public void caretUpdate(CaretEvent e) {
        if (!update) {
          update = true;
          setCaretPosition(getText().length());
          update = false;
        }
      }
    });
    // limpa o campo se apertar DELETE
    addKeyListener(new KeyAdapter() {

      @Override
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_DELETE) {
          setText("");
        }
      }
    });
    // formato inicial
    setText("0");
    setCaretPosition(getText().length());
  }

  /**
   * Define um valor BigDecimal ao campo
   * 
   * @param value
   */
  public void setValue(BigDecimal value) {
    super.setText(numberFormat.format(value));
  }

  /**
   * Recupera um valor BigDecimal do campo
   * 
   * @return
   */
  public final BigDecimal getValue() {
    return new BigDecimal(getText().replaceAll("[^0-9]", "")).divide(new BigDecimal(Math.pow(10, numberFormat
        .getMaximumFractionDigits())));
  }

  /**
   * Recupera o formatador atual do campo
   * 
   * @return
   */
  public NumberFormat getNumberFormat() {
    return numberFormat;
  }

  /**
   * Define o formatador do campo
   * 
   * @param numberFormat
   */
  public void setNumberFormat(NumberFormat numberFormat) {
    this.numberFormat = numberFormat;
  }

  /**
   * Preenche um StringBuilder com zeros
   * 
   * @param zeros
   * @return
   */
  private static final String makeZeros(int zeros) {
    if (zeros >= 0) {
      StringBuilder builder = new StringBuilder();

      for (int i = 0; i < zeros; i++) {
        builder.append('0');
      }
      return builder.toString();
    } else {
      throw new RuntimeException("Número de casas decimais inválida (" + zeros + ")");
    }
  }

  /**
   * Recupera o limite do campo.
   * 
   * @return
   */
  public int getLimit() {
    return limit;
  }

  /**
   * Define o limite do campo, limit < 0 para deixar livre (default) Ignora os pontos e virgulas do formato, conta
   * somente com os números
   * 
   * @param limit
   */
  public void setLimit(int limit) {
    this.limit = limit;
  }

  // testes, pode ser removido
  public static void main(String[] args) {
    JFrame frame = new JFrame("Teste do campo");
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setResizable(false);
    frame.add(new JNumberFormatField(new DecimalFormat("0.000")) {

      {
        // limita a 4 caracteres
        setLimit(4);
      }
    });
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

21 Respostas

C

Legal, ficou otimo

Eu não consegui executar o comando getValue()

Quando eu jogo ele no netbeans e tento usar este metodo ao inves do getText ele reclama que não existe

Tem como limitar o tamanho do campo também? tipo quero um campo para CFOP 5.102, teria que ter 3 decimais e caber apenas um inteiro

Dario

D

O problema é do NetBeans…
remove o componente da paleta, fecha, abre e adiciona denovo
Quanto ao seu problema mudei um pouco o código
para suportar limitações no campo.

Abs,

C

Quanto ao netbeans ta tranquilo, nem joguei pra paleta

Eu to criando direto como custom code mas eu acho que to fazendo errado na hora de querer pegar o valor

To fazendo

valor.getValue() ele diz que não existe este metodo

Criei o objeto no custom code do TextField assim

new JNumberFormatField(new DecimalFormat("0.00")) {
      {
        setLimit(6);
      }
    }

Dario

D

Esse é o seu problema então,
o NetBeans declarou o TextField como
JtextField…
não importa que vc fez um custom com JNumberFormatField,
pro Java o que interessa é o tipo na declaração, e não na instancialização (new).
Adicione o JNumberformatField na paleta ou mude o tipo da variavel
para JNumberformatField, ou em ultimo caso faça um cast

// desse jeito o java enchergará
((JNumberFormatField)seuCampoDeTexto).getValue();

e vê se estuda mais o Java, que tal o eclipse?
o NetBeans ta te deixando “por fora” da linguagem creio eu…

Abs,

C

Entendi,

Quero tentar alterar o codigo para que ele se inicialize assim:

new JNumberFormatField(14,2)

onde 14 eh a quantidade de caracteres que ele pode aceitar incluindo o ponto

e 2 eh o numero de decimais que ele vai ter ja incluso no numero 14

por exemplo (6,2) seria 999.99

Obrigado

Dario

C

Dyorgio

Parabens,

Consegui implementar o código para meu proposito, alterei apenas as linhas do código abaixo:

public JNumberFormatField(int casasTotal, int casasDecimais) {
      this(new DecimalFormat((casasDecimais == 0 ? "#,##0" : "#,##0.") + makeZeros(casasDecimais)));
      this.setLimit(casasTotal-1);
  }

  public JNumberFormatField(int casasTotal) {
      this(new DecimalFormat((0 == 0 ? "#,##0" : "#,##0.") + makeZeros(0)));
      this.setLimit(casasTotal);
  }
  
  public JNumberFormatField() {
      this(new DecimalFormat((2 == 0 ? "#,##0" : "#,##0.") + makeZeros(2)));
      this.setLimit(14-1);
  }

Agora posso iniciar com:

new JNumberFormatField() -> ele pega um padrão default

new JNumberFormatField(11) -> ele pega um inteiro com 11 posições

new JNumberFormatField(6,2) -> ele pega um campo fracionario com 6 posições incluindo a virgula e com duas decimais

Obrigadão,

Dario

ps. você já fez um código deste tipo para formatar DATAS onde ele permita que se digite 13/10/77 e ele já complemente ao sair do campo para 13/10/1977 e ainda não deixe sair do campo se a data for invalida?

Dario.

P

Ola vc tem ai um codigo para resolver este problema:

Como fazer auto-incremento no PostGreSql usando String no campo codigo e preencher com zeros a esquerda

C

Colocar zeros a esquerda eh simples,

public String strZero( int value, int n ){
        String s = Integer.toString( value ).trim();
        StringBuffer resp = new StringBuffer();
        int fim = n - s.length();
        for( int x = 0; x < fim; x++ )
          resp.append( '0' );
        return resp + s;
    }

Quanto ao autoincrement o proprio postgreSQL faz isto, é só você criar uma tabela com um campo AUTOINCREMENT

Dario

P

vc criou uma string e como aplicar nos campos?

Outra coisa é como usar um codigo de um tabela para formar o codigo de outra.

ex.

cad-bairro… tem o campo codigo da cidade, o codigo da cidade for 0000002
o codigo do primeiro bairro sera gerado no momento que eu clicar em gravar como 0000021.

pode me ajudar com isso tambem.

obrigado

D

Dario, esse seu auto complete é meio arriscado,
no exemplo qeu vc colocou esta certo, pois 77 na nossa época esta mais para a década de 90,
mais se o cara digitar 55?
o correto seria colocar para 2055…já que esta mais para o século 21,
ai o cara preenche a data de nascimento dele e vai pro século 21 haehahehaheahe
o ideal, e que é o mais encontrado por ai, é a digitação da data completa,
ou algo com combos…
Pessoalmente eu prefiro combos, assim vc nem precisa se preocupar com datas inválidas,
da pra colocar o mês em string tb :P, Janeiro, fevereiro
ainda da pra fazer com JSpinner tb…

Abs,

A
dyorgio:
Oi pessoal, com base no sucesso do meu outro tópico (JMoneyField) decidi colocar um novo campo que pode ser usado como monetario... esse código é mais maduro e muito mais personalizavel :P aproveitem, comentem, e melhorem!!!
// Pacote aoqual a classe pertence
package neocode.lib.graphic.field;

// Importa as bibilotecas Java necessárias
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/**
 * Campo para a inserção de números com base em um formato.
 * 
 * @author Dyorgio da Silva Nascimento
 */
public class JNumberFormatField extends JTextField {

  private static final long serialVersionUID = -7506506392528621022L;

  private static final NumberFormat MONETARY_FORMAT = new DecimalFormat(&quot;#,##0.00&quot;);

  private NumberFormat numberFormat;

  private int limit = -1;

  public JNumberFormatField(int casasDecimais) {
    this(new DecimalFormat((casasDecimais == 0 ? &quot;#,##0&quot; : &quot;#,##0.&quot;) + makeZeros(casasDecimais)));
  }

  public JNumberFormatField() {
    this(MONETARY_FORMAT);
  }

  public JNumberFormatField(NumberFormat format) {
    // define o formato do número
    numberFormat = format;
    // alinhamento horizontal para o texto
    setHorizontalAlignment(RIGHT);
    // documento responsável pela formatação do campo
    setDocument(new PlainDocument() {

      private static final long serialVersionUID = 1L;

      @Override
      public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        String text = new StringBuilder(JNumberFormatField.this.getText().replaceAll(&quot;[^0-9]&quot;, &quot;&quot;)).append(
            str.replaceAll(&quot;[^0-9]&quot;, &quot;&quot;)).toString();
        super.remove(0, getLength());
        if (text.isEmpty()) {
          text = &quot;0&quot;;
        }else{
          text = new BigInteger(text).toString();
        }

        super.insertString(0, numberFormat.format(new BigDecimal(getLimit() &gt; 0 && text.length() &gt; getLimit() ? text
            .substring(0, getLimit()) : text).divide(new BigDecimal(Math.pow(10, numberFormat
            .getMaximumFractionDigits())))), a);
      }

      @Override
      public void remove(int offs, int len) throws BadLocationException {
        super.remove(offs, len);
        if (len != getLength()) {
          insertString(0, &quot;&quot;, null);
        }
      }
    });
    // mantem o cursor no final do campo
    addCaretListener(new CaretListener() {

      boolean update = false;

      @Override
      public void caretUpdate(CaretEvent e) {
        if (!update) {
          update = true;
          setCaretPosition(getText().length());
          update = false;
        }
      }
    });
    // limpa o campo se apertar DELETE
    addKeyListener(new KeyAdapter() {

      @Override
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_DELETE) {
          setText(&quot;&quot;);
        }
      }
    });
    // formato inicial
    setText(&quot;0&quot;);
    setCaretPosition(getText().length());
  }

  /**
   * Define um valor BigDecimal ao campo
   * 
   * @param value
   */
  public void setValue(BigDecimal value) {
    super.setText(numberFormat.format(value));
  }

  /**
   * Recupera um valor BigDecimal do campo
   * 
   * @return
   */
  public final BigDecimal getValue() {
    return new BigDecimal(getText().replaceAll(&quot;[^0-9]&quot;, &quot;&quot;)).divide(new BigDecimal(Math.pow(10, numberFormat
        .getMaximumFractionDigits())));
  }

  /**
   * Recupera o formatador atual do campo
   * 
   * @return
   */
  public NumberFormat getNumberFormat() {
    return numberFormat;
  }

  /**
   * Define o formatador do campo
   * 
   * @param numberFormat
   */
  public void setNumberFormat(NumberFormat numberFormat) {
    this.numberFormat = numberFormat;
  }

  /**
   * Preenche um StringBuilder com zeros
   * 
   * @param zeros
   * @return
   */
  private static final String makeZeros(int zeros) {
    if (zeros &gt;= 0) {
      StringBuilder builder = new StringBuilder();

      for (int i = 0; i &lt; zeros; i++) {
        builder.append('0');
      }
      return builder.toString();
    } else {
      throw new RuntimeException(&quot;Número de casas decimais inválida (&quot; + zeros + &quot;)&quot;);
    }
  }

  /**
   * Recupera o limite do campo.
   * 
   * @return
   */
  public int getLimit() {
    return limit;
  }

  /**
   * Define o limite do campo, limit &lt; 0 para deixar livre (default) Ignora os pontos e virgulas do formato, conta
   * somente com os números
   * 
   * @param limit
   */
  public void setLimit(int limit) {
    this.limit = limit;
  }

  // testes, pode ser removido
  public static void main(String[] args) {
    JFrame frame = new JFrame(&quot;Teste do campo&quot;);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setResizable(false);
    frame.add(new JNumberFormatField(new DecimalFormat(&quot;0.000&quot;)) {

      {
        // limita a 4 caracteres
        setLimit(4);
      }
    });
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
Boa noite Caro amigo, estou precisando de uma focinha estive olhando essa class sua e achei muito interessante então pensei em usar, mais ai é q ta o problema não estou sabendo usa a sua class será q vc pode me da uma ajuda.
A

no momento estou usando essa daqui ate q esta atendendo a minha necessidade, mas tem um problema não consigo seta o valor q vem do banco para o campo q recebe essa implementação e infelizmente não sei implementa essa funcionalidade nesse código.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Util;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/**
 *
 * @author kelow
 */
public class MonetarioDocument extends PlainDocument {

    private static final NumberFormat MONETARY_FORMAT = new DecimalFormat("R$ #,##0.00");
    public static final int NUMERO_DIGITOS_MAXIMO = 12;

    @Override
    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() < MonetarioDocument.NUMERO_DIGITOS_MAXIMO) {
            super.remove(0, getLength());
            texto = texto.replace(".", "").replace(",", "");
            StringBuilder s = new StringBuilder(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);
    }
    
    

}

então para o momento só queria q ele fizer o retorno do banco de dado para o campo. Deste já agradeço a colaboração dos colegas do guj. Um forte abraço a tds.

D

Opa,

Cara, verifica se quando você esta setando o valor que vem do banco, o mesmo não esta com algum ponto ou virgula,
pois o seguin te trecho do código invalida esse tipo de input:

if (!Character.isDigit(c)) {  
                return;  
            }
A

Bom dia dyorgio, realmente ele vem como Double do banco e percebi q ele invalida agora como eu devo fazer para consegui representa esse valor no JFormattedTextField.

D

Você tem trescaminhos,

  1. Antes de setar o valor no campo, converte para string porem multiplica antes para não perder casas decimais, por exemplo 1.23 = String.valueOf((int)(1.23*100)) = “123”

  2. Ajustar seu codigo para aceitar os pontos…porem você esta no lugar errado caso esteja buscando ajuste no seu código, aqui é um tópico sobre o codigo postado acima.

  3. Usar o código que esta nesse topico, o mesmo já trabalha com BigDecimal (que possui construtor que aceita double).

G

Galera eu to fazendo um função usando essa classe só que ai acontece o seguinte
A função ta lisa eu vou postar a linha mais ou menos como eu fiz.

public void PegaValor (JNumberFormatField valor) { int numero = Integer.valueOf(valor.getValue().toString()); }
na hora de declarar ficaria assim

só que na hora que eu declaro a função da erro como se eu tivesse pondo um outro objeto la alguem me ajuda por favor

W

Boa tarde. Mais de uma ano e esse tópico ainda é muito útil.
Minha duvida é, como alterar este código para que no lugar da vírgula como separador decimal eu coloque um ponto?
Tentei simplesmente alterar o código colocando ponto no lugar de virgula e/ou virgula no lugar de ponto, mas nada da certo.
Preciso do ponto como separador decimal, pois o valor digitado irá para o banco de dados que só aceita ponto e não vírgula.

dyorgio:
Oi pessoal, com base no sucesso do meu outro tópico (JMoneyField) decidi colocar um novo campo que pode ser usado como monetario... esse código é mais maduro e muito mais personalizavel :P aproveitem, comentem, e melhorem!!!
// Pacote aoqual a classe pertence
package neocode.lib.graphic.field;

// Importa as bibilotecas Java necessárias
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/**
 * Campo para a inserção de números com base em um formato.
 * 
 * @author Dyorgio da Silva Nascimento
 */
public class JNumberFormatField extends JTextField {

  private static final long serialVersionUID = -7506506392528621022L;

  private static final NumberFormat MONETARY_FORMAT = new DecimalFormat(&quot;#,##0.00&quot;);

  private NumberFormat numberFormat;

  private int limit = -1;

  public JNumberFormatField(int casasDecimais) {
    this(new DecimalFormat((casasDecimais == 0 ? &quot;#,##0&quot; : &quot;#,##0.&quot;) + makeZeros(casasDecimais)));
  }

  public JNumberFormatField() {
    this(MONETARY_FORMAT);
  }

  public JNumberFormatField(NumberFormat format) {
    // define o formato do número
    numberFormat = format;
    // alinhamento horizontal para o texto
    setHorizontalAlignment(RIGHT);
    // documento responsável pela formatação do campo
    setDocument(new PlainDocument() {

      private static final long serialVersionUID = 1L;

      @Override
      public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        String text = new StringBuilder(JNumberFormatField.this.getText().replaceAll(&quot;[^0-9]&quot;, &quot;&quot;)).append(
            str.replaceAll(&quot;[^0-9]&quot;, &quot;&quot;)).toString();
        super.remove(0, getLength());
        if (text.isEmpty()) {
          text = &quot;0&quot;;
        }else{
          text = new BigInteger(text).toString();
        }

        super.insertString(0, numberFormat.format(new BigDecimal(getLimit() &gt; 0 && text.length() &gt; getLimit() ? text
            .substring(0, getLimit()) : text).divide(new BigDecimal(Math.pow(10, numberFormat
            .getMaximumFractionDigits())))), a);
      }

      @Override
      public void remove(int offs, int len) throws BadLocationException {
        super.remove(offs, len);
        if (len != getLength()) {
          insertString(0, &quot;&quot;, null);
        }
      }
    });
    // mantem o cursor no final do campo
    addCaretListener(new CaretListener() {

      boolean update = false;

      @Override
      public void caretUpdate(CaretEvent e) {
        if (!update) {
          update = true;
          setCaretPosition(getText().length());
          update = false;
        }
      }
    });
    // limpa o campo se apertar DELETE
    addKeyListener(new KeyAdapter() {

      @Override
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_DELETE) {
          setText(&quot;&quot;);
        }
      }
    });
    // formato inicial
    setText(&quot;0&quot;);
    setCaretPosition(getText().length());
  }

  /**
   * Define um valor BigDecimal ao campo
   * 
   * @param value
   */
  public void setValue(BigDecimal value) {
    super.setText(numberFormat.format(value));
  }

  /**
   * Recupera um valor BigDecimal do campo
   * 
   * @return
   */
  public final BigDecimal getValue() {
    return new BigDecimal(getText().replaceAll(&quot;[^0-9]&quot;, &quot;&quot;)).divide(new BigDecimal(Math.pow(10, numberFormat
        .getMaximumFractionDigits())));
  }

  /**
   * Recupera o formatador atual do campo
   * 
   * @return
   */
  public NumberFormat getNumberFormat() {
    return numberFormat;
  }

  /**
   * Define o formatador do campo
   * 
   * @param numberFormat
   */
  public void setNumberFormat(NumberFormat numberFormat) {
    this.numberFormat = numberFormat;
  }

  /**
   * Preenche um StringBuilder com zeros
   * 
   * @param zeros
   * @return
   */
  private static final String makeZeros(int zeros) {
    if (zeros &gt;= 0) {
      StringBuilder builder = new StringBuilder();

      for (int i = 0; i &lt; zeros; i++) {
        builder.append('0');
      }
      return builder.toString();
    } else {
      throw new RuntimeException(&quot;Número de casas decimais inválida (&quot; + zeros + &quot;)&quot;);
    }
  }

  /**
   * Recupera o limite do campo.
   * 
   * @return
   */
  public int getLimit() {
    return limit;
  }

  /**
   * Define o limite do campo, limit &lt; 0 para deixar livre (default) Ignora os pontos e virgulas do formato, conta
   * somente com os números
   * 
   * @param limit
   */
  public void setLimit(int limit) {
    this.limit = limit;
  }

  // testes, pode ser removido
  public static void main(String[] args) {
    JFrame frame = new JFrame(&quot;Teste do campo&quot;);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setResizable(false);
    frame.add(new JNumberFormatField(new DecimalFormat(&quot;0.000&quot;)) {

      {
        // limita a 4 caracteres
        setLimit(4);
      }
    });
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
S

Muito bom seu componente, já uso ele há algum tempo, porém estou tendo uma única dificuldade, valor negativos, pelo o que eu testei ele não aceita valores negativos, você tem algum tratamento para esses casos?

Obrigado.

R

Aceitar números negativos

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/**
 * Campo para a inserção de números com base em um formato.
 *
 * @author Dyorgio da Silva Nascimento
 */
public class JNumberFormatField extends JTextField {

    private static final long serialVersionUID = -7506506392528621022L;
    private static final NumberFormat MONETARY_FORMAT = new DecimalFormat("R$ #,##0.00");
    private NumberFormat numberFormat;
    private int limit = -1;

    public JNumberFormatField(int casasDecimais) {
        this(new DecimalFormat((casasDecimais == 0 ? "#,##0" : "#,##0.") + makeZeros(casasDecimais)));
    }

    public JNumberFormatField() {
        this(MONETARY_FORMAT);
    }

    public JNumberFormatField(NumberFormat format) {// define o formato do
        // número
        numberFormat = format;// alinhamento horizontal para o texto
        setHorizontalAlignment(RIGHT);// documento responsável pela formatação
        // do campo
        setDocument(new PlainDocument() {
            private static final long serialVersionUID = 1L;

            @Override
            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
                String first = (!JNumberFormatField.this.getText().isEmpty()) ? String.valueOf(JNumberFormatField.this.getText().charAt(0)) : "";
                String fStr = (!str.isEmpty()) ? String.valueOf(str.charAt(0)) : "";
                String text = new StringBuilder(JNumberFormatField.this.getText().replaceAll("[^0-9]", "")).append(str.replaceAll("[^0-9]", "")).toString();

                super.remove(0, getLength());
                if (text.isEmpty()) {
                    text = "0";
                } else {
                    text = new BigInteger(text).toString();
                }

                BigDecimal n = new BigDecimal(getLimit() > 0 == text.length() > getLimit() ? text.substring(0, getLimit()) : text).divide(new BigDecimal(Math.pow(10, numberFormat.getMaximumFractionDigits())));

                if (str.equals("-") || first.equals("-") || fStr.equals("-")) {
                    n = n.multiply(new BigDecimal(-1));
                }

                super.insertString(0, numberFormat.format(n), a);
            }

            @Override
            public void remove(int offs, int len) throws BadLocationException {
                super.remove(offs, len);
                if (len != getLength()) {
                    insertString(0, "", null);
                }
            }
        });// mantem o cursor no final
        // do campo
        addCaretListener(new CaretListener() {
            boolean update = false;

            @Override
            public void caretUpdate(CaretEvent e) {
                if (!update) {
                    update = true;
                    setCaretPosition(getText().length());
                    update = false;
                }
            }
        });// limpa o campo se
        // apertar DELETE
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_DELETE) {
                    setText("");
                }
            }
        });// formato
        // inicial
        setText("0");
        setCaretPosition(getText().length());
    }

    /**
     * *
     * Define um valor BigDecimal ao campo**
     *
     * @param value
     */
    public void setValue(BigDecimal value) {
        super.setText(numberFormat.format(value));
    }

    /**
     * *
     * Recupera um valor BigDecimal do campo**
     *
     * @return
     */
    public final BigDecimal getValue() {
        String first = (!getText().isEmpty()) ? String.valueOf(getText().charAt(0)) : "0";

        BigDecimal valor = new BigDecimal(getText().replaceAll("[^0-9]", "")).divide(new BigDecimal(Math.pow(10, numberFormat.getMaximumFractionDigits())));
        if (first.equals("-")) {
            valor = valor.multiply(new BigDecimal(-1));
        }
        return valor;
    }

    /**
     * *
     * Recupera o formatador atual do campo**
     *
     * @return
     */
    public NumberFormat getNumberFormat() {
        return numberFormat;
    }

    /**
     * *
     * Define o formatador do campo** @param numberFormat
     */
    public void setNumberFormat(NumberFormat numberFormat) {
        this.numberFormat = numberFormat;
    }

    /**
     * *
     * Preenche um StringBuilder com zeros** @param zeros*
     *
     * @return
     */
    private static final String makeZeros(int zeros) {
        if (zeros >= 0) {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < zeros; i++) {
                builder.append('0');
            }
            return builder.toString();
        } else {
            throw new RuntimeException("Número de casas decimais inválida (" + zeros + ")");
        }
    }

    /**
     * *
     * Recupera o limite do campo.** @return
     */
    public int getLimit() {
        return limit;
    }

    /**
     * *
     * Define o limite do campo, limit < 0 para deixar livre (default) Ignora os
     * pontos e virgulas do formato, conta* somente com os números** @param
     * limit
     */
    public void setLimit(int limit) {
        this.limit = limit;
    }

    // testes, pode ser removido
    public static void main(String[] args) {
        JFrame frame = new JFrame("Teste do campo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setResizable(false);
        frame.add(new JNumberFormatField() {
            {// limita a 4
                // caracteres
                setLimit(4);
            }
        });
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
M

Pessoal… uma dúvida. Como configuraria um campo que vem do DB para aparecer formatado no JNumberFormatField… tipo…: txtSalarioBase.setText(rs.getString(“cal_salario_base”));

D

Ola, isso já deve resolver:

txtSalarioBase.setValue(rs.getBigDecimal(“cal_salario_base”))

Criado 24 de julho de 2008
Ultima resposta 29 de mar. de 2018
Respostas 21
Participantes 9