2

The first thing I do is create a NumberFormat that is appropriate to my needs:

this.format = NumberFormat.getIntegerInstance();
this.format.setMinimumIntegerDigits(6);
this.format.setMaximumIntegerDigits(6);
this.format.setGroupingUsed(false);

I then apply it to a JFormattedTextField:

this.fld_id = new JFormattedTextField(this.format);

I then set this field's InputVerifier, like so:

this.fld_id.setInputVerifier(new IdVerifier());

My IdVerifier simply looks to see that the entered text conforms to a regular expression:

private class IdVerifier extends InputVerifier {
        public boolean verify(final JComponent arg0) {
            final JFormattedTextField verifyJTF = (JFormattedTextField) arg0;

            if (!verifyJTF.getText().matches("\\d{6}")) {
                return false;
            }

            return true;
        }

        public boolean shouldYieldFocus(final JComponent arg0) {
            if (!this.verify(arg0)) {
                arg0.setBackground(Color.RED);
            } else {
                arg0.setBackground(UIManager.getColor("TextField.background"));
            }

            return true;
        }
}

However, when I do this, I enter a value into the JFormattedTextField, let's say "1". This gets reformatted to "000001" by the NumberFormatter. However, in this example, the background of the text field is still set to red.

What is the correct way to ensure that the formatted contents of the JFormattedTextField are what gets consumed by the InputVerifier? I expected the default behavior to be that the focus is lost, the formatter is applied, then the input is verified. However, that's clearly not the case.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Thomas Owens
  • 114,398
  • 98
  • 311
  • 431

2 Answers2

0

Looking at the definition for InputVerifier, it does not sound like GUI work should be taking place inside either the verify or shouldYieldFocus methods. The InputVerifier is solely intended to make the decision as to whether focus should jump from one field to another.

I think you'd be better off attaching an ActionListener to your JFormattedTextField and then simply calling your regex and red-painting code in the body of that listener. Then the check will be made each time the content of the text field changes.

Bobulous
  • 12,967
  • 4
  • 37
  • 68
  • In [the tutorials, in the "Validating Input" section](http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html#inputVerification), they do beeping in the InputVerifier. What in the definition of InputVerifier makes it seem like you shouldn't be doing things to the GUI in it, especially to the JComponent that the InputVerifier has access to? – Thomas Owens Apr 24 '13 at 17:55
  • Good point, and even though the description for `shouldYieldFocus` simply says "calls verify() to make sure input is valid" it does mention that the method can have side effects. But I still think that an ActionListener is a better fit, and I think it would solve your problem where the NumberFormatter is concerned. – Bobulous Apr 24 '13 at 18:06
  • I'll look into using an ActionListener instead, but it just seems like weird behavior. I confirmed that in verify(), the text of the input argument is indeed the value before formatting. I guess I just expected the formatter to be called before the verifier, so that you verify against formatted input (for example, against a regex like I'm doing). – Thomas Owens Apr 24 '13 at 18:09
  • But the InputVerifier is only called when the field loses focus, so it is not called when the NumberFormatter changes its value. An ActionListener should be called in both cases. – Bobulous Apr 24 '13 at 19:12
  • That's true. I guess I made the assumption that the NumberFormatter would be called before the InputVerifier, when the field loses focus. – Thomas Owens Apr 24 '13 at 21:45
-1

Change the regular expression to be \\d{1,6}, it probably doesn't accept the leading zeros as a number

Mr Rho
  • 578
  • 3
  • 16
  • It's been a long time since I've done GUI work, but the [Oracle tutorials suggest doing it my way](http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html), which is why I did it. In the section called "Validating Input", they call a beep method in the `shouldYieldFocus()` method. I don't see the difference between changing the color of a field and beeping. This may be a bad example in the tutorials, but I don't see how moving the background setting from the `verify()` method to the `shouldYieldFocus()` method will solve anything. – Thomas Owens Apr 24 '13 at 17:46
  • Yeah, also read it now, my bad - perhaps it has to do with the regular epxression... read my updated entry. – Mr Rho Apr 24 '13 at 17:47
  • That changes the meaning of my regular expression, though. It will probably work because of the formatter, but I don't want to rely on the formatter being present. {1,6} means at least 1 but not more than 6 times - the only valid input is exactly 6 digits. – Thomas Owens Apr 24 '13 at 17:51
  • @MrRho The problem is not with the validity of the regex, but with the way the code is executing. – Bobulous Apr 24 '13 at 17:54
  • Agreed, apologies for the mislead. – Mr Rho Apr 24 '13 at 17:54