Search code examples
javaswingjtextfielddocumentfilter

Using Document FIlter to filter multiple periods(.)


Lets say a user has to input a Double value into the Jtextfield which then gets calculated.
But if the user suddenly used more than 1 period it would trigger a NumberFormatException, so i assume the solution would be using a Document Filter to filter out any extra periods or catching the exception and notifying the user of an invalid input

Currenty using a DocumentFilter to only allow digits and periods, but my problem is how to filter out a second period

PlainDocument filter = new PlainDocument();
            filter.setDocumentFilter(new DocumentFilter() {
                    @Override
                    public void insertString(FilterBypass fb, int off, String str, AttributeSet attr) 
                    throws BadLocationException 
                    {
                    fb.insertString(off, str.replaceAll("[^0-9.]", ""), attr);
                    } 
                    @Override
                    public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr) 
                    throws BadLocationException 
                    {
                    fb.replace(off, len, str.replaceAll("[^0-9.]", ""), attr);
                    }
            });

            apm.setDocument(filter);

Example

Invalid INPUT: 1.2.2

Valid INPUT: 1.22


Solution

  • My suggestion is that you could change the overridden insertString and replace methods so that it checks whether any "." has been inserted earlier before this insert or replace and change the filter in a way that the 'period' would be replaced by a blank string if any subsequent time the period character is inserted by the user. I have illustrated as below:

    @Override
    public void insertString(FilterBypass fb, int off, String str, AttributeSet attr) 
                    throws BadLocationException {
        String regExp;
        Document doc = fb.getDocument();
        if(doc.getText(0, doc.getLength()).indexOf(".") == -1){
            regExp = "[^0-9.]";
        } else {
            regExp = "[^0-9]";
        }
        fb.insertString(off, str.replaceAll(regExp, ""), attr);
    }
    
    @Override
    public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr) 
                    throws BadLocationException {
        String regExp;
        Document doc = fb.getDocument();
        if(doc.getText(0, doc.getLength()).indexOf(".") == -1){
            regExp = "[^0-9.]";
        } else {
            regExp = "[^0-9]";
        }
        fb.replace(off, len, str.replaceAll(regExp, ""), attr);
    }
    

    The above code will only allow the 'period' to be inserted just once in the Document to which this DocumentFilter is set.