1

I have 4 JTextFields that should only accept certain characters:

  1. binary digits (0, 1)
  2. octal digits, so (0 - 7)
  3. all digits (0 - 9)
  4. all hexadecimal characters (0 - 9, a - f, A - F)

The user must not be able to input a forbidden character.

I know how I could validate the input afterwards, but not how to filter it.


I tried using a MaskFormatter, but then I can't enter anything at all.

MaskFormatter binaryFormatter = new MaskFormatter();
binaryFormatter.setValidCharacters("01");
JFormattedTextField binaryText = new JFormattedTextField(binaryFormatter);
Scriptim
  • 1,743
  • 2
  • 20
  • 37
  • Can you share the code with what you have tried so far? – lenz Jun 12 '15 at 22:06
  • 1
    Use a DocumentFilter on a normal JTextField instead – MadProgrammer Jun 12 '15 at 22:09
  • how? can you give me a code example – Scriptim Jun 12 '15 at 22:11
  • 2
    [Implementing a DocumntFilter](https://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter) and [Examples](http://www.jroller.com/dpmihai/entry/documentfilter) – MadProgrammer Jun 12 '15 at 22:16
  • You could pass the formatted text field a [`MaskFormatter`](http://docs.oracle.com/javase/7/docs/api/javax/swing/text/MaskFormatter.html) which specifies valid characters – Vince Jun 12 '15 at 22:16
  • Convert your requirements into a `java.text.Format`, and use it in combination with the `JFormattedTextField`, as shown [here](http://stackoverflow.com/a/13424140/1076463) – Robin Jun 13 '15 at 13:25

1 Answers1

3

You don't want to format the value, you want to filter the content. Use a DocumentFilter on a plain on JTextField

Start by having a look at Implementing a DocumntFilter and Examples for more details...

As an example, a "binary filter", which will only accept 0 and 1

public class BinaryDocumentFilter extends DocumentFilter {
    @Override
    public void insertString(DocumentFilter.FilterBypass fb, int offset,
            String text, AttributeSet attr)
            throws BadLocationException {
        StringBuilder buffer = new StringBuilder(text.length());
        for (int i = text.length() - 1; i >= 0; i--) {
            char ch = text.charAt(i);
            if (ch == '0' || ch == '1') {
                buffer.append(ch);
            }
        }
        super.insertString(fb, offset, buffer.toString(), attr);
    }

    @Override
    public void replace(DocumentFilter.FilterBypass fb,
            int offset, int length, String string, AttributeSet attr) throws BadLocationException {
        if (length > 0) {
            fb.remove(offset, length);
        }
        insertString(fb, offset, string, attr);
    }
}

Which can be applied directly to the field's Document:

JTextField binaryField = new JTextField(10);
((AbstractDocument)binaryField.getDocument()).setDocumentFilter(new BinaryDocumentFilter());
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • at super.insertString(fb, offset, buffer.toString(), **attr**); – Scriptim Jun 12 '15 at 22:54
  • and at **@Override** public void replace(){} – Scriptim Jun 12 '15 at 22:54
  • 1
    @Scriptim You're importing the wrong `AttributeSet`, you need `javax.swing.text.AttributeSet` and forgive me, but I've been using this technique for more the 15 years and works just fine. The `DocumentFilter` is the best mechanism for restricting (or filtering) content into text components – MadProgrammer Jun 13 '15 at 00:07
  • Is it possible that `new StringBuilder(text.length())` was intended to be `new StringBuilder(text)`? Otherwise an empty `StringBuilder` of some size is created, though I don't understand how `buffer.charAt(i)` would ever yield something useful, since the buffer is not filled. Am I not seeing something? – Koenigsberg Sep 08 '22 at 14:39
  • @Koenigsberg First, we create a `StringBuffer` of the same length as in the coming text (as this is the maximum number of characters we will need - avoids the possibility that the `StringBuffer` will need to expand it's internal cache). We then go through the text and only include `0` or `1` characters, all the rest are discarded. And `buffer.charAt(i);` should probably be `text.charAt(i);` – MadProgrammer Sep 08 '22 at 22:02
  • @MadProgrammer Okay. So my assumption about the buffer being empty in the original code was correct. – Koenigsberg Sep 09 '22 at 10:18