Search code examples
javaswingjtextfield

JTextfield Dynamically adding text while typing


I have a 'formatted' field - that is that it must be finally in a form like this: xx/xxxx/xx I'd like to make it so that while typing you get the '/' added automatically.

The way that I am trying to cobble together is something like this:

JTextField field = new JTextField ("xx/xxxx/xx");

// a focus listener to clear the "xx/xxxx/xx" on focus & restore on focus-out
// the override the 'document' with this:
field.setDocument (new PlainDocument () {
    public void insertString (int off, String str, AttributeSet attr) throws BadLocationException {
      if (off == 2 || off == 7) {
        super.insertString (off + 1, str + "/", attr);
      }
    }
}

This seems like it is going to break - and how do I properly deal with when it goes from: xx/xx.. to xx? I think having them delete the '/' is ok.

I feel there should be a better way? Maybe a library I could use? Something other than my...special stuff.

Thanks for any input you have!!


Solution

  • To achieve this I did this:

    JTextField field = new JTextField ();
    
    field.setDocument (new PlainDocument () {
      public void insertString (int off, String str, AttributeSet attr) throws BadLocationException {
        if (off < 10) {  // max size clause
          if (off == 1 || off == 6) { // insert the '/' occasionally
            str = str + "/";
          }
          super.insertString (off, str, attr);
        }
      }
    });
    
    field.setText ("xx/xxxx/xx"); // set AFTER otherwise default won't show up!
    field.setForeground (ColorConstants.DARK_GRAY_080); // make it light! 
    field.addFocusListener (new ClearingFocusListener (field)); // could be done in an anonymous inner class - but I use it other places
    
    private static class ClearingFocusListener implements FocusListener {
      final private String initialText;
      final private JTextField field;
    
      public ClearingFocusListener (final JTextField field) {
        this.initialText = field.getText ();
        this.field = field;
      }
    
      @Override
      public void focusGained (FocusEvent e) {
        if (initialText.equals (field.getText ())) {
          field.setText ("");
          field.setForeground (ColorConstants.DARK_GRAY_080);
        }
      }
    
      @Override
      public void focusLost (FocusEvent e) {
        if ("".equals (field.getText ())) {
          field.setText (initialText);
          field.setForeground (ColorConstants.LIGHT_GRAY_220);
        }
      }
    }
    

    This is different that the other solution in that the '/' doesn't exist when there is no text, it is added at the right places. It doesn't currently doesn't deal with any of the replacement stuff -- eh. :/