0

How to restrict a JTextFiled to accept only numbers less then 10, no words, no spaces or any other special characters?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
user3210099
  • 9
  • 1
  • 2

4 Answers4

4

The easiest would be to use a component designed for this:

JSpinner spinner = new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, null, 10, 1));

Technically JSpinner is not derived from JTextField, it uses one internally for the editor part and thus looks like one (plus it has additional buttons to change the number with mouse clicks).

Hauke Ingmar Schmidt
  • 11,559
  • 1
  • 42
  • 50
3

Again, a DocumentFilter is one way to solve this:

import javax.swing.*;
import javax.swing.text.*;

@SuppressWarnings("serial")
public class DocFilterExample extends JPanel{
   JTextField textfield = new JTextField(5);

   public DocFilterExample() {
      PlainDocument doc = (PlainDocument) textfield.getDocument();
      doc.setDocumentFilter(new MaxNumberDocFilter(10));

      add(textfield);
   }

   private class MaxNumberDocFilter extends DocumentFilter {
      private int maxNumber;

      public MaxNumberDocFilter(int maxnumber) {
         this.maxNumber = maxnumber;
      }

      private boolean verifyText(String text) {
         if (text.isEmpty()) {
            return true; // allow for a blank text field
         }
         int value = 0;
         try {
            value = Integer.parseInt(text);
            if (value >= 0 && value < maxNumber) {
               return true; // if it's a number in range, it passes
            }
         } catch (NumberFormatException e) {
            return false;  // if it's not a number, it fails.
         }
         return false;
      }

      @Override
      public void insertString(FilterBypass fb, int offset, String string,
               AttributeSet attr) throws BadLocationException {

         Document doc = fb.getDocument();
         String oldText = doc.getText(0, doc.getLength());
         StringBuilder sb = new StringBuilder(oldText);
         sb.insert(offset, string);

         if (verifyText(sb.toString())) {
            super.insertString(fb, offset, string, attr);
         }

      }

      @Override
      public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
               throws BadLocationException {
         Document doc = fb.getDocument();
         String oldText = doc.getText(0, doc.getLength());
         StringBuilder sb = new StringBuilder(oldText);

         sb.replace(offset, offset + length, text);
         if (verifyText(sb.toString())) {
            super.replace(fb, offset, length, text, attrs);
         }
      }

      @Override
      public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
         Document doc = fb.getDocument();
         String oldText = doc.getText(0, doc.getLength());
         StringBuilder sb = new StringBuilder(oldText);

         sb.replace(offset, offset + length, "");

         if (verifyText(sb.toString())) {
            super.remove(fb, offset, length);            
         }
      }
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Eg");
      frame.getContentPane().add(new DocFilterExample());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}
  • Advantages:
    • no error messages are needed. Instead it simply prevents input of bad input.
    • It works for cut and paste just fine.
  • Disadvantages:
    • no error messages are given, and so the user won't know why his text is not accepted.
    • it's a bit long and bulky.
    • it's not easy "chaining" -- using multiple filters at once, something Rob Camick has done some work on.
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

Try This :-

JTextField textField = new JTextField();

textField.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
         //do stuff here when enter pressed
        String text = textField.getText();
        if(text!=null && !text.equals("")){
            char c = evt.getKeyChar();
            int val=Integer.parseInt(c);
            if(val>=48 && val<=57){
                if(Integer.parseInt(text)<=10){
                    //Its valid and allowed
                }else{
                    //Its invalid, show error message here
                }
            }else{
                //Show message only numbers are allowed
                return false;
            }           
        }

    }
});

Hope it will help you.

JDGuide
  • 6,239
  • 12
  • 46
  • 64
  • An `ActrionListener` will only be fired when the enter key is pressed. Either of the other answers provides a better solution here. – Andrew Thompson Jan 18 '14 at 21:37
-1

Use Swing Javabuilders, where you can define your GUI in YML (below), including Text Field validation.

You declare in your gui in a yaml file, here is an example for Person.java, called Person.Yaml:

JFrame(name=frame, title=frame.title, size=packed, defaultCloseOperation=exitOnClose):
        - JButton(name=save, text=button.save, onAction=[$validate,save,done])
        - JButton(name=cancel, text=button.cancel, onAction=[$confirm,cancel])
        - MigLayout: |
              [pref]              [grow,100]     [pref]             [grow,100]
              "label.firstName"   txtFirstName   "label.lastName"   txtLastName
              "label.email"       txtEmail+*
              >save+*=1,cancel=1
    bind:
        - txtFirstName.text: person.firstName
        - txtLastName.text: person.lastName
        - txtEmail.text: person.emailAddress
    validate:
        - txtFirstName.text: {mandatory: true, label: label.firstName}
        - txtLastName.text: {mandatory: true, label: label.lastName}
        - txtEmail.text: {mandatory: true, emailAddress: true, label: label.email}

The three blocks above are as follows:

The Swing Classes (JFrame, and JButton) as well as the Layout Manager, with embedded JLabels (label.firstName and label.lastName) which are recognised by the 'label' part of their declaration and the JTextFields (txtLastName,txtFirstName and txtEmail ) which are recognised by the txt part of their name.

The Data Binding: This binds JTextArea.text to class.fieldName so that when data is entered into the JTextField it is mapped to the fields.

Validation: Here is where the text is validated. Notice that the JButton with the name Save has in the onAction section has the entry $validate which runs the in-built validate method. This reads the kind of validation in from the validate block:

 txtFirstName.text: {mandatory: true, label: label.firstName}

Which declares the field has to be filled in (mandatory: true) and txtEmail must be filled with a valid email address (emailAddress: true). More validation is outlined below.

Once you've declared the GUI, you just run it like so, from within your java file.

    private BuildResult result;
    .....
    public methodName(){
        .....
    result = SwingJavaBuilder.build(this).setVisible(true);
    }

This method (build(this)) references a .yml file of the same name (so your gui is in person.yml and is paired with person.java).

There's more validation available in the documentation :

validate:
      - mandatory.text: {label: Mandatory Field, mandatory: true}
      - date.text: {label: Date Field, dateFormat: "yyyy/mm/dd"}
      - email.text: {label: E-Mail, email: true}
      - minmax.text: {label: Min/Max Length, minLength: 5, maxLength: 10}
      - regex.text: {label: Regex, regex: "[a-zA-Z0-9]+"}
      - regex2.text: {label: Regex, regex: "[a-zA-Z0-9]+", 
               regexMessage: "''{0}'' must be a number or letter"}
      - long.text: {label: Min/Max Long, minValue: 5, maxValue: 50, mandatory: true}

So you would want to use the last one long.text with this specification:

myValidNumberField{label: Number less than ten, maxValue: 10, mandatory: true}`

There's more information on the github page, about setting your GUI up like this.

AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173