3

I'm trying to implement requirements like:

Accept only numbers in JTextield, when a non-digit key pressed, it will not be accepted.

I tried many stuff, even tried to call the backspace event to remove the last character if it's a non-digit. However, not able to remove the value typed in the textfield. I tried to understand DOCUMENT FILTER but finding it difficult to implement. I will be glad if anyone helps me to resolve the issue.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Alex Michael Raj
  • 185
  • 2
  • 9
  • 24
  • 1
    Use a JFormattedTextField : http://docs.oracle.com/javase/7/docs/api/javax/swing/JFormattedTextField.html. How to use : http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html – Alexis C. Dec 12 '13 at 10:44
  • 1
    Duplicate. See http://stackoverflow.com/a/11093360/2791703 – dARKpRINCE Dec 12 '13 at 10:47
  • 2
    Use a [`JSpinner`](http://docs.oracle.com/javase/tutorial/uiswing/components/spinner.html) – MadProgrammer Dec 12 '13 at 11:15

4 Answers4

10

Use DocumentFilter. Here is simple example with regex:

JTextField field = new JTextField(10);
((AbstractDocument)field.getDocument()).setDocumentFilter(new DocumentFilter(){
        Pattern regEx = Pattern.compile("\\d*");

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {          
            Matcher matcher = regEx.matcher(text);
            if(!matcher.matches()){
                return;
            }
            super.replace(fb, offset, length, text, attrs);
        }
    });

field is your JTextField, and this filter allow to enter only digits.

Gigi Bayte 2
  • 838
  • 1
  • 8
  • 20
alex2410
  • 10,904
  • 3
  • 25
  • 41
  • Just curious, what's the difference between overriding the `replace` and `insertString`? I'm not too familiar with the `DocumnetFilter`, but just by the name of the method, would `insertString` be better for this situation? Enlighten me :) – Paul Samsotha Dec 12 '13 at 11:04
  • _"It also overrides the replace method, which is most likely to be called when the user pastes in new text"_. That's from the tutorial you linked to. It sound like `replace` is more for pasted text. Am I wrong? – Paul Samsotha Dec 12 '13 at 11:08
  • Also from text, _"insertString method, which is called each time that text is inserted into the document."_. – Paul Samsotha Dec 12 '13 at 11:09
  • @peeskillet `insertString(...)` invokes only when you directly insert text to document like next `field.getDocument().insertString(...);`. So you need to override `replace()` method. – alex2410 Dec 12 '13 at 11:11
  • Still can't upvote because of those terrible variable names. arg0, arg1... mean absolutely nothing to anyone looking at the code. – camickr Dec 12 '13 at 16:13
  • @camickr haven't attached docs to eclipse, because I have args... ) have replaced that from docs) – alex2410 Dec 12 '13 at 16:34
1

You can use a MaskFormatter and pass it as the Format argument to the JFormattedTextField constructor.

"The MaskFormatter class implements a formatter that specifies exactly which characters are valid in each position of the field's text" - MaskFormatter tutorial

This example will only allow user to enter digits. I set it to allow only 6 digits, but you can change that number with more or fewer #'s.

import java.awt.BorderLayout;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.MaskFormatter;

public class MaskFormatterTest extends JPanel {

    private JFormattedTextField formatText;

    public MaskFormatterTest() {
        formatText = new JFormattedTextField(createFormatter("######"));
        formatText.setColumns(20);

        setLayout(new BorderLayout());
        add(new JLabel("Enter only numbers"), BorderLayout.NORTH);
        add(formatText, BorderLayout.CENTER);
    }

    private MaskFormatter createFormatter(String s) {
        MaskFormatter formatter = null;
        try {
            formatter = new MaskFormatter(s);
        } catch (java.text.ParseException exc) {
            System.err.println("formatter is bad: " + exc.getMessage());
            System.exit(-1);
        }
        return formatter;
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("MaskFormatter example");
                frame.add(new MaskFormatterTest());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLocationByPlatform(true);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks for your answers.. but the code which alex2410 posted works as i expected.. In your code I am not able to insert the values in-between i.e. if i erase the numbers using DELETE key there is a space b/w two digits.. otherwise yours also works good. – Alex Michael Raj Dec 13 '13 at 09:11
  • This seems to be mildly abusing the JFormattedTextField. This class provides a means to alter the presentation of entered text, not to force the input text to conform to a format/charset - although it does permit you to reject the input should parsing for display fail. The accepted answer is more correct as it uses the APIs in their intended fashion. – Azeroth2b Aug 06 '20 at 14:34
  • MaskFormatter allows only an exact length of numbers, it is not variable – Sonny Benavides Sep 05 '22 at 11:46
-3

This is the simple way to create numbers only jTextField,

    jTextField1 = new javax.swing.JTextField();

    jTextField1.addKeyListener(new java.awt.event.KeyAdapter() {

        public void keyReleased(java.awt.event.KeyEvent evt) {
            try {
                long number = Long.parseLong(jTextField1.getText());
            } catch (Exception e) {
                JOptionPane.showMessageDialog(rootPane, "Only Numbers Allowed");
                jTextField1.setText("");
            }
        }
    });
Naveen S
  • 49
  • 9
-3

You can add a keyListener and cancel the KeyTyped event if the pressed key is not a number.

        textField.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent evt) {
                if (!Character.isDigit(evt.getKeyChar())) {
                    evt.consume();
                }
            }
        });
Coderman69
  • 69
  • 7