1

I know this is a common question, but I'm trying to create a TextField that only accept int numbers, and it's almost done, here's the code:

Create textfield:

nome = new JFormattedTextField();
            nome.setHorizontalAlignment(SwingConstants.CENTER);
            nome.setColumns(2);

            DocumentFilter filtro = new FiltroNumero();
            ((AbstractDocument) nome.getDocument()).setDocumentFilter(filtro);

            panel.add(nome);

DocummentFilter:

public class FiltroNumero extends DocumentFilter{

    public void insertString(DocumentFilter.FilterBypass fb, int offset, int length,
              String text, javax.swing.text.AttributeSet attr)

              throws BadLocationException {
                    fb.insertString(offset, text.replaceAll("[^-0-9]", ""), attr);
         }  
}

With this, the TextField will only accept numbers and "-", but it means that "1-" is a possible value.

What I need is a way to make the textfield don't accept the minus after the first character.

If someone can help me, I'll be really glad :)

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • 1
    You should either check to see if the text is equal to (or contains `-`) and that it is at the start, when the value's are appended... – MadProgrammer Oct 23 '14 at 02:47
  • @MadProgrammer either that, or only allow 0-9 for each individual char, I feel that would check for even more issues that would come in the future, especially since that is a part of the parameters – DreadHeadedDeveloper Oct 23 '14 at 02:49
  • 1
    @DreadHeadedDeveloper I was think that you could also check for the existence of the `-` character, remove it from the incoming `String` and insert it at the beginning of the document, depending on if it existed or not already...so pressing `-` would always put it at the start (or end based on the needs) – MadProgrammer Oct 23 '14 at 02:51
  • @MadProgrammer ah, I stand corrected – DreadHeadedDeveloper Oct 23 '14 at 02:52
  • Consider also a `JSpinner` with `SpinnerNumberModel`.. – Andrew Thompson Oct 23 '14 at 05:05

1 Answers1

3

You could simply get the entire text from the Document (which is the before replace), then create a new String from that document text, adding the text argument. Then just check against a complete regex that matches integers (negative or positive). If it matches, then do the replace. Something like:

@Override
public void replace(FilterBypass fb, int offs, int length,
        String str, AttributeSet a) throws BadLocationException {

    String text = fb.getDocument().getText(0,
            fb.getDocument().getLength());

    StringBuilder builder = new StringBuilder(text);
    builder.insert(offs, str);
    String newText = builder.toString();

    // check
    System.out.println("text = " + text 
                   + ", offset = " + offs 
                   + ", newText = " + newText);

    if (newText.matches("(-)?\\d*")) {
        super.replace(fb, offs, length, str, a);
    } else {
        Toolkit.getDefaultToolkit().beep();
    }
}

Note: you should be using replace rather than insertString, though doesn't hurt to override both.

Here's a complete demo

import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class FilterDemo {

    public FilterDemo() {
        JFrame frame = new JFrame();
        frame.add(createFilteredField());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

    }

    private  JTextField createFilteredField() {
        JTextField field = new JTextField(10);
        AbstractDocument document = (AbstractDocument) field.getDocument();
        document.setDocumentFilter(new DocumentFilter() {

            @Override
            public void replace(FilterBypass fb, int offs, int length,
                    String str, AttributeSet a) throws BadLocationException {

                String text = fb.getDocument().getText(0,
                        fb.getDocument().getLength());

                StringBuilder builder = new StringBuilder(text);
                builder.insert(offs, str);
                String newText = builder.toString();

                // check
                System.out.println("text = " + text 
                               + ", offset = " + offs 
                               + ", newText = " + newText);

                if (newText.matches("(-)?\\d*")) {
                    super.replace(fb, offs, length, str, a);
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }
            }


            @Override
            public void insertString(FilterBypass fb, int offs, String str,
                    AttributeSet a) throws BadLocationException {

                String text = fb.getDocument().getText(0,
                        fb.getDocument().getLength());

                StringBuilder builder = new StringBuilder(text);
                builder.insert(offs, str);
                String newText = builder.toString();

                // checks
                System.out.println("text = " + text 
                               + ", offset = " + offs 
                               + ", newText = " + newText);

                if (newText.matches("(-)?\\d*")) {
                    super.insertString(fb, offs, str, a);
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }
            } 
        });
        return field;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new FilterDemo();
            }
        });
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720