Java Tips Weblog

  • Blog Stats

    • 2,570,383 hits
  • Categories

  • Archives

Text Prompt

Posted by Rob Camick on November 29, 2009

Generally text fields are paired with a label when added to a GUI. The label describes the contents of the text field. In some applications you may have noticed that a text prompt appears inside an empty text field. This might be done when space is at a premium or you need to provide addition formatting information for the text.

The TextPrompt class allows you to add this functionality to a text field. The implementation takes advantage of the Swing design that allows you to add child components to any Swing component. So a JLabel containing the prompt text is added to the text field. The main functionality of the TextPrompt class is to determine whether the prompt should be visible or not. The prompt will be removed as soon as text is entered into the Document.

When the Document is empty, the setShow method allows yout to control when the prompt is visible:

  • ALWAYS – the prompt is displayed whether the text field has focus or not.
  • FOCUS_GAINED – the prompt is displayed when the text field gains focus (and is hidden when focus is lost)
  • FOCUS_LOST – the prompt is displayed when the text field loses focus (and is hidden when focus is gained)

There is only one other method that allows you control the behaviour of the prompt:

  • setShowPromptOnce – will only display the prompt once. After the text field loses focus for the first time the prompt will no longer be visible.

The Font and foreground Color of the TextPrompt will default from the text field at the time the TextPrompt is created. However, there are a couple of convenience methods that will allow you to customize the appearance of the text in the prompt:

  • changeAlpha – allows you to change the alpha value of the foreground Color to provide some transparency
  • changeStyle – allows you to change the style of the Font. The values allowed are those supported by the Font class. Common values might be Font.BOLD, Font.ITALIC or Font.BOLD + Font.ITALIC

The code to create the last prompt in the above image was:

JTextField tf7 = new JTextField(10);
TextPrompt tp7 = new TextPrompt("First Name", tf7);
tp7.setForeground( Color.RED );
tp7.changeAlpha(0.5f);
tp7.changeStyle(Font.BOLD + Font.ITALIC);
tp7.setIcon( ... );

Notice the setIcon() method? As mentioned earlier, the TextPrompt simply extends JLabel to provide its functionality so you can change any property of the label to achieve your desired effect. Be creative, who knows what effect you can achieve!

Although this discussion has dealt with using the TextPrompt on a text field, it can also be used on a JTextArea or JTextPane as well. Using it on a JFormattedTextField that contains formatting characters may prove to be more difficult. I’ll let you experiment with that on your own.

Another option would be to use the PromptSupport class found in the SwingX project. SwingX provides many enhancements to base Swing.

Get The Code

TextPrompt.java
TextPromptDemo.java

34 Responses to “Text Prompt”

  1. Kleopatra said

    Elegance by simplicity :-)

    Good job!
    Jeanette

  2. Luke Nezda said

    Great concept and implementation! However, at least on OS X, defaults used for JNLP demo are such that the text of all prompts have their text’s top aligned at the center of the field which clips the bottom part of this text. Not sure if field or child or both need explicit setAlignmentY or setHorizontalAlignment or setHorizontalTextPosition or something. Also, the second column of labels in the gui has its leading textual content clipped (e.g., first row label reads “ow Always (default)”). Must need some pack()ing or FontMetric tricks or something. Sorry to gripe, great article: I didn’t know you could do have this functionality in so little code.

    • Rob Camick said

      > all prompts have their text’s top aligned at the center of the field which clips the bottom part of this text

      I was using “setVerticalAlignment(JLabel.TOP);”. I removed that line so it defaults to “CENTER” and it seems to paint better.

      > the second column of labels in the gui has its leading textual content clipped

      Yes, I tend to create the image using setSize(). I forgot to change it back to pack(). It should be better now.

      Thanks, for the feedback.

  3. i30817 said

    xswingx has this. I’m using it (with a patch that is in the tracker but not applied since it appears that the author doesn’t look at the project anymore)

    • Kleopatra said

      the xswingx version is part of SwingX – so would be great if you could file your patch in the swingx issue tracker, we’ll happily apply it :-)

      Thanks
      Jeanette

  4. Elegant…This should definitely be added to the Sun official docs.

    Regards,
    Pavan

  5. Prajin said

    I received this Exception message when I tried to use the code in my work.


    java.lang.NullPointerException
    at ...TextPrompt.(TextPrompt.java:50)
    at ...TextPrompt.(TextPrompt.java:43)
    .......

    this(text, component, Show.ALWAYS); // -> TextPrompt.java:43

    document = component.getDocument(); // -> Textprompt.java:50

    This is what I wrote in my Main Frame code :

    TextPrompt txtShortCode = new TextPrompt("Number only!", shortCodeField);

    -by the way,thanks for this tip

  6. Jörg said

    Hello Rob,

    just implemented your code. It works great. Thank you very much.

    In case somebody needs it for a JTextField which is displayed repeatedly and must according to condition show the textprompt or not, here are the few modifications necessary to achieve this:

    – add NEVER to enum Show
    – change private void checkForPrompt() to protected
    – add “if (!showPromptOnce) focusLost= 0;” in method setShowPromptOnce(…)

    Implementation example:
    TextPrompt tp= new TextPrompt(…);

    if (condition) {
    tp.setShow(TextPrompt.Show.NEVER);
    }
    else {
    tp.setShowPromptOnce(false); // clear focusLost counter
    tp.setShow(TextPrompt.Show.ALWAYS);
    tp.setShowPromptOnce(true);
    }
    tp.checkForPrompt(); // make the new setShow(…) value visible.

  7. Jadd said

    It would be great if you could include a BSD style license header in the source code so that I could use the code without worrying about copyright.

  8. Dilawar said

    Thnx… Saved my a** and an hour :P

  9. mike said

    Nice trick, you saved my day. :D But I have to note that it works by chance, not by design. On the other hand, I realize that no one will ever design a TextFieldUI that’s not a full-size, empty rectangle. Good job.

  10. maneesh godbole said

    Hi Rob,
    I used your TextPrompt.java Nice work! Thanks!
    For better usability(IMO) I modified it a bit.
    1) set the foreground to Color.LIGHT_GRAY so as to avoid confusion between input text and the prompt text
    2) Used the prompt text as a tool tip for the text component. This is useful when input text exists and you wish to know what this field represents.

    Thanks again! As always you are awesome!

  11. Anjith Sasindran said

    Good job man.. Why didn’t you use GitHub to share this code??

  12. Karl said

    Can I use this in my own software without a license?

  13. Anonymous said

    More than 5 years later : thank you guy, simple and efficient

  14. For some reason when I try to implement to my program it show the label but not the actual text field. Anyone know why?
    Thanks!

  15. Banuka said

    I want to know is there a library for this Text Prompt??? Please if you have give me a link

  16. Ivan Gredyaev said

    I have to say it’s the most elegant implemantation of the feature!
    Only one thing I had to add to your solution is passing focus to the text component on mouse press:

    // CTOR code fragment
    addMouseListener(new MouseAdapter() { 
        @Override
        public void mouseClicked(MouseEvent e) {
             component.requestFocusInWindow();
        }
    });
    
    • Rob Camick said

      Not sure why you need to use the MouseListener. The text field gets focus when you click on it. This is the whole basis of how the “FOCUS_GAINED” property works. When the text field gets focus, it removes the prompt so you can start typing. I’m using Windows 7 on JDK 8.

      • Ivan Gredyaev said

        To be honest I’m not so experienced in using Swing. I’ve just realized that click on the prompt is not making it invisible and had to find some workaround.
        Probably I shoud check my one more time in order to fine the cause that leads to the effect.

      • Rob Camick said

        The default is to “ALWAYS” display the prompt if no text has been entered into the text field.

        Did you try using the setShow(…) method to change the default behaviour?

  17. Simon Robinson said

    Hi, yes brilliant works really well for me also. However I’m trying to use it on the JTextComponent as provided by an editable JComboBox (the return value from combo.getEditor().getEditorComponent() but it the label text doesn’t seem to show… can you think of the reason that might be preventing this please? Perhaps the default combo renderer selection is sitting in front?

    • Rob Camick said

      Works for me. The combo must be editable and there must be no selected item:

      comboBox.setSelectedIndex( -1 );
      comboBox.setEditable( true );
      JTextField tf = (JTextField)comboBox.getEditor().getEditorComponent();
      TextPrompt tp = new TextPrompt("Select", tf);
      
      • Simon Robinson said

        Thanks for the response, so it does! Should have checked with using the basic JCombo first before posting, that means the extension we are using to JComboBox must be doing something to prevent this from working correctly. Time to crack open the debugger.

      • Simon Robinson said

        Problem solved, some weirdness with a that custom editor! Thanks again.

  18. Griefed said

    You absolute madlad, you did it again. I was blown away by your SmartScroller and BackgroundPanel, and now you’ve gone and made THIS wonderful thing.

    Genius, absolute genius. Thank you so very much for sharing your work. You have no idea how valuable your work is to me.

    Cheers,
    Griefed

Leave a comment