Bloqueio de caracteres em Jtextfield

Boa tarde Pessoal !

Gostaria de uma ajuda referente a bloqueio de caracteres em um jtextfield. No meu caso tenho feito dessa forma, código abaixo. Onde o campo recebe apenas números e virgula, porem gostaria de que o campo não aceitasse mais de uma virgula. Pesquisei bastante e não consegui encontrar.

private void txt_taraKeyTyped(java.awt.event.KeyEvent evt) {                                  
    // TODO add your handling code here:
   String caracteres = "0123456789,";
   if (!caracteres.contains(evt.getKeyChar()+"")){
   evt.consume();
   }

Alguem? :bowing_man:

Você pode aplicar um DocumentFilter que utilize expressões regulares para filtrar conteúdo, aí é só setar ele no seu JTextField, veja o exemplo abaixo:

Primeiro um DocumentFilter que utiliza expressões regulares (regex) para validar seu conteúdo:

class RegexFilter extends DocumentFilter {

    private final String regex;

    public RegexFilter(String regex) {
        this.regex = regex;
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attrs) throws BadLocationException {
        Document document = fb.getDocument();
        String text = document.getText(0, document.getLength());
        if ((text + string).matches(regex)) {
            super.insertString(fb, offset, string, attrs);
        }
    }
}

Agora é só definir uma regex para aceitar somente dígitos e somente uma vírgula.
Criar um filtro com essa regex.
Atribuir o filtro ao JTextField:

String regex = "\\d*\\,?\\d*";
RegexFilter filter = new RegexFilter(regex);
((AbstractDocument) meuObjetoJTextField.getDocument()).setDocumentFilter(filter);
1 curtida

Boa tarde Staroski

Primeiramente muito obrigado pela resposta, porem ainda estou tendo dificuldades para aplicar essa solução, não estou conseguindo intender em qual momento é chamado o metodo replace da minha classe DocumentFilterComER, segue a baixo o código, daclasse e tambem do meo Jframe que contem o jtextfield.

public class DocumentFilterComER extends DocumentFilter {

private final String regex;

public DocumentFilterComER(String regex){
   //super();
    this.regex = regex;      
}

public void replace (FilterBypass fb, int offset, int length, String string, AttributeSet attrs) throws BadLocationException{
//fb.replace(offset, length, text.replaceAll(this.er, “”), (javax.swing.text.AttributeSet) attrs);
System.out.println(“TESTE”);
Document document = fb.getDocument();
String text = document.getText(0, document.getLength());
if ((text + string).matches(regex)) {
super.replace(fb, offset, length, text, (javax.swing.text.AttributeSet) attrs);
System.out.println("Text: ");
}
}

Abaixo é minha duvida, fiz dessa forma no evento keytyped, me desculpe caso seja algo simples porem sou novo e estou aprendendo ainda rs.

private void txt_numeroKeyTyped(java.awt.event.KeyEvent evt) {                                    
 String regex = "\\d*,?\\d*";
 DocumentFilterComER filter = new DocumentFilterComER(regex);
 ((AbstractDocument) txt_numero.getDocument()).setDocumentFilter(filter);

}

Todo TextComponent do Swing encapsula um Document no qual você pode pôr um filtro.

Quando você seta um DocumentFilter para um Document ele vai chamar os métodos desse DocumentFilter quando você inserir algum valor no componente.

Pode remover o KeyListener, você não vai tratar pressionamento de teclas.

Você vai filtrar o conteúdo digitado no JTextField.

Você vai definir o DocumentListener logo após ter feito o txt_numero = new JTextField();

txt_numero = new JTextField(); // instanciou
((AbstractDocument) txt_numero.getDocument()).setDocumentFilter(new DocumentFilterComER("\\d*\\,?\\d*")); // setou o filtro