Search code examples
javaregexvalidationjtextfield

What is the regular expression for valdating a 'price' in a jtextfield


I want to validate a jtextfield as user inputs a price of some item.

I have a perfectly working code which beeps and discard if user inputs some character that doesnt match the regular expression.(for regular expression "[0-9]+" it accepts any number of digits and beeps if a letter is given as input)

But the problem is I want to validate an input like "12500.00". Format should be any number of digits before decimal point and two digits after the decimal point. eg: ddd.dd

I tried the following regular expression. But the i doesnt allow user to input "." character. It allows user to input any number of digits but when "." key is pressed input is not accepted.

here is the regular expression I used. "[0-9]+ | [0-9]+. | [0-9]+.[0-9]{1} | [0-9]+.[0-9]{2}"

important: user input is validated character by character as the user inputs them to the jtextfield.

Here is the code

import java.awt.Toolkit;
import java.util.regex.Pattern;
import javax.swing.JComponent;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public abstract class ValidatedTextField extends PlainDocument {

private int max;
private String regExp;

public ValidatedTextField(int max, String regExp) {
    this.max = max;
    this.regExp = regExp;

}

@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
    Pattern DIGITS = Pattern.compile(regExp);
    // System.out.println(str);
    if (getLength() + str.length() > max) {
        str = str.substring(0, max - getLength());
        Toolkit.getDefaultToolkit().beep();
    }
    if (!DIGITS.matcher(str).matches() || str == null) {
        str = null;
        Toolkit.getDefaultToolkit().beep();
    }
    if (str != null && !passDependency(str)) {
        str = null;
        Toolkit.getDefaultToolkit().beep();
    }
    //str != null && DIGITS.matcher(str).matches

    super.insertString(offs, str, a);

}

public abstract boolean passDependency(String str);

public void shiftFocus(JComponent jc, boolean condition) {
    if (condition) {
        jc.requestFocusInWindow();
    }
}
}

Below is not the exact code but this is how I use it.

import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;

public class ValidateTest {
void makeFrame(){
    JFrame jf=new JFrame("Verifier Test");
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextField text = new JTextField();
    JLabel lbl=new JLabel("Price");

    text.setDocument(new ValidatedTextField(10, "[0-9]+") {

        @Override
        public boolean passDependency(String str) {
            return true;
        }
    });
    text.setPreferredSize(new Dimension(200, 30));
    lbl.setPreferredSize(new Dimension(60, 30));
    jf.getContentPane().add(text, BorderLayout.EAST);
    jf.getContentPane().add(lbl, BorderLayout.WEST);
    jf.pack();
    jf.setVisible(true);
    text.setVisible(true);
}
public static void main(String[] args) {
    new ValidateTest().makeFrame();
}
}

Solution

  • You are doing too much and a regex is not always the solution.

    Use a JFormattedTextField with the amountFormat

    See Sun's Java tutorial and demo