Only allowing numbers and a symbol (-) to be typed into a JTextField
Asked Answered
G

3

2

I'm trying to create a math quiz and I only want the user to be able to enter numbers whether they're negative or positive. Is there any way to do so? I've thought of using Regular Expressions but I've heard that they are bad to use. I tried using a keylistener but then what if the user pastes? I've tried parsing the string to get an integer but then the negative symbol will not work.

Any ideas?

package com.quiz.ui;

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class SSCCE {

    private JFrame frame;

    private JPanel contentPane;

    private JTextField usernameField;

    public static void main(String[] arguments) {
        new SSCCE().construct();
    }

    public void construct() {
        frame = new JFrame("Login");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(getContentPane());
        frame.pack();
        frame.setVisible(true);
    }

    public JPanel getContentPane() {
        usernameField = new JTextField(5);
        usernameField.addKeyListener(new KeyListener() {

            @Override
            public void keyPressed(KeyEvent arg0) {
                int keyCode = arg0.getKeyCode();
                if ((keyCode > 47 && keyCode < 58) || keyCode == 45) {
                    arg0.consume();
                }
                System.out.println(arg0.getKeyCode());
            }

            @Override
            public void keyReleased(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void keyTyped(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }
        });

        contentPane = new JPanel(new BorderLayout());
        contentPane.add(usernameField);

        return contentPane;
    }

}
Gilligan answered 5/11, 2011 at 2:45 Comment(0)
T
12

Use DocumentFilter:

NumberOnlyFilter.java:

import javax.swing.*;
import javax.swing.text.*;
import java.util.regex.*;
public class NumberOnlyFilter extends DocumentFilter
{

    public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException
    {
        StringBuilder sb = new StringBuilder();
        sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
        sb.insert(offset, text);
        if(!containsOnlyNumbers(sb.toString())) return;
        fb.insertString(offset, text, attr);
    }
    public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr) throws BadLocationException
    {
        StringBuilder sb = new StringBuilder();
        sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
        sb.replace(offset, offset + length, text);
        if(!containsOnlyNumbers(sb.toString())) return;
        fb.replace(offset, length, text, attr);
    }

    /**
     * This method checks if a String contains only numbers
     */
    public boolean containsOnlyNumbers(String text)
    {
        Pattern pattern = Pattern.compile("([+-]{0,1})?[\\d]*");
        Matcher matcher = pattern.matcher(text);
        boolean isMatch = matcher.matches();
        return isMatch;
    }

}

and then you can use it like:

((AbstractDocument)yourTxtField.getDocument()).setDocumentFilter(new NumberOnlyFilter());
Torrie answered 5/11, 2011 at 2:55 Comment(10)
+1 I'm always tempted to pre-compile the pattern, but the profiled benefit is usually marginal.Scotch
The problem with this is the symbol - needs to be allowed as well.Gilligan
@Ron: Eng's suggestion is a great one (1+), and you can use Eng's suggestion and allow - easily by either parsing the String to see if it is an appropriate numeric representation, or using other logic within the filter.Keelia
The adjustLabel(...) method cannot be found.Gilligan
@Ron Oops, I always copy this code from my old files, and forget to remove adjustLabel(), sorry :)Torrie
Thanks :) Would you happen to know how to modify your Regular Expression to include the - symbol? I looked before asking this questions and couldn't find anything.Gilligan
@Torrie It seems as though I can only type one character when using this filter, any ideas why? It seems to be happening because of the containsOnlyNumbers(...) method.Gilligan
@Ron I am not familiar with regex so I am not sure why. Try [\\d] and test if you can type more than one digit.Torrie
@Torrie I have tried "[-+]?\\d+" and it lets me type multiple integers but I cannot use + or -Gilligan
@Ron um, try this one: ([+-]{0,1})?[\\d]*Torrie
S
4

Alternatively, consider Validating Input using an InputVerifier. A Formatted Text Field may also be suitable.

Scotch answered 5/11, 2011 at 2:53 Comment(0)
U
0

You can use Integer.parseInt(String s, int radix), for decimal use 10 as a redix value.

Undoubted answered 5/11, 2011 at 2:56 Comment(2)
The negative symbol does not pass the test when using this method.Gilligan
i haven't tried the code, but this link says, it will return the negative value, [link](download.oracle.com/javase/1.4.2/docs/api/java/lang/…, int))Undoubted

© 2022 - 2024 — McMap. All rights reserved.