1

I am familiar that you can input text before hand into a JTextField. This text will be displayed in the JTextField and has to be manually deleted when having to input your own text into the JTextField. For example, consider this JTextField:

cruiseSel = new JTextField ("Selected Cruise:");
cruiseSel.setEditable(false);  
centerP12.add(cruiseSel);
contentPane12.add(centerP12, BorderLayout.CENTER);
Frame12.setVisible(true);

Upon running the above, a JTextField will appear with "Selected Cruise:" written within it. This text then has to be manually deleted to clear the text field.

Is there a way to input text in an JTextField, so once the GUI opens, the text will be displayed, but when the JTextField is selected to input manual text, the text vanishes?

Freddy
  • 683
  • 4
  • 35
  • 114

5 Answers5

3

You could use a FocusListener and when the JTextField receives focus, empty the text.

Of course you will want a state marker to indicate it has the default text and not do this once you have user entered text. Either that or after the FocusListener is hit the first time, remove it.

textField.addFocusListener(new FocusAdapter() {
    public void focusGained(FocusEvent e) {
        JTextField source = (JTextField)e.getComponent();
        source.setText("");
        source.removeFocusListener(this);
    }
});
tddmonkey
  • 20,798
  • 10
  • 58
  • 67
2

What you are looking for is called placeholder. I've written this class a while ago:

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

/**
 * @author xehpuk
 */
public class PlaceholderTextField extends JTextField {
    private static final long serialVersionUID = -5529071085971698388L;

    /**
     * The placeholder to be displayed if the text field is empty.
     */
    private String placeholder;
    /**
     * Determines whether the placeholder should be displayed even on focus.
     */
    private boolean paintingOnFocus;
    /**
     * The color the placeholder should be displayed in.
     */
    private Color placeholderColor;

    public String getPlaceholder() {
        return placeholder;
    }

    public void setPlaceholder(final String placeholder) {
        this.placeholder = placeholder;
        repaint();
    }

    public boolean isPaintingOnFocus() {
        return paintingOnFocus;
    }

    public void setPaintingOnFocus(final boolean paintingOnFocus) {
        this.paintingOnFocus = paintingOnFocus;
        repaint();
    }

    public Color getPlaceholderColor() {
        return placeholderColor;
    }

    public void setPlaceholderColor(final Color placeholderColor) {
        this.placeholderColor = placeholderColor;
        repaint();
    }

    public PlaceholderTextField() {
        super();
    }

    public PlaceholderTextField(final Document doc, final String text, final int columns) {
        super(doc, text, columns);
    }

    public PlaceholderTextField(final int columns) {
        super(columns);
    }

    public PlaceholderTextField(final String text, final int columns) {
        super(text, columns);
    }

    public PlaceholderTextField(final String text) {
        super(text);
    }

    {
        addFocusListener(new RepaintFocusListener());
    }

    @Override
    protected void paintComponent(final Graphics g) {
        super.paintComponent(g);
        if (getPlaceholder() != null && getText().isEmpty() && (isPaintingOnFocus() || !isFocusOwner())) {
            try {
                final Rectangle rect = getUI().modelToView(this, 0);
                final Insets insets = getInsets();
                g.setFont(getFont());
                g.setColor(getPlaceholderColor() == null ? getForeground() : getPlaceholderColor());
                ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                g.drawString(getPlaceholder(), rect.x, getHeight() - insets.top - insets.bottom - rect.y);
            } catch (final BadLocationException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private class RepaintFocusListener implements FocusListener {
        @Override
        public void focusGained(final FocusEvent e) {
            repaint();
        }

        @Override
        public void focusLost(final FocusEvent e) {
            repaint();
        }
    }
}

You can choose the text and the color and whether it should be painted even if the text field has focus.

The crucial part is the overriding of paintComponent(Graphics).

xehpuk
  • 7,814
  • 3
  • 30
  • 54
1

You can use SwingX Read on this How to set Text like Placeholder in JTextfield in swing I include the sample code here for your use

import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.swingx.prompt.PromptSupport;

public class PromptExample {

    public static void main(String[] args) {
        new PromptExample();
    }

    public PromptExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JTextField bunnies = new JTextField(10);
                JTextField ponnies = new JTextField(10);
                JTextField unicorns = new JTextField(10);
                JTextField fairies = new JTextField(10);

                PromptSupport.setPrompt("Bunnies", bunnies);
                PromptSupport.setPrompt("Ponnies", ponnies);
                PromptSupport.setPrompt("Unicorns", unicorns);
                PromptSupport.setPrompt("Fairies", fairies);

                PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, bunnies);
                PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIGHLIGHT_PROMPT, ponnies);
                PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.SHOW_PROMPT, unicorns);

                PromptSupport.setFontStyle(Font.BOLD, bunnies);
                PromptSupport.setFontStyle(Font.ITALIC, ponnies);
                PromptSupport.setFontStyle(Font.ITALIC | Font.BOLD, unicorns);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                frame.add(bunnies, gbc);
                frame.add(ponnies, gbc);
                frame.add(unicorns, gbc);
                frame.add(fairies, gbc);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}
Community
  • 1
  • 1
1

Check out Text Prompt.

It supports this functionality along with a couple of features to customize the behaviour of the prompt.

camickr
  • 321,443
  • 19
  • 166
  • 288
-1

To achieve something like this, you would generally need to create a certain type of event listener. In your case, the desired action needs to be triggered on a mouse event - thus the MouseAdapter event listener seems like a good fit (at first glance). To use the MouseAdapter abstract class, you'd need to extend it and override the necessary methods (see here for a full list of available methods).

The shortest way of achieving this is via an anonymous class declaration, like so:

cruiseSel.addMouseListener(new MouseAdapter(){
    @Override
    public void mouseClicked(MouseEvent e){
        cruiseSel.setText("");
    }
});

(However, if you need to override multiple methods or the triggered logic feels complex enough, you might be better off creating a separate listener class.)

EDIT: Alternatively, as @HovercraftFullOfEels pointed out in the comment section, it would probably be wiser to apply the FocusAdapter class (see here) in an identical fashion:

cruiseSel.addFocusListener(new FocusAdapter(){
    @Override
    public void focusGained(FocusEvent e){
        cruiseSel.setText("");
    }
});

The problem with the first solution is that it is only concerned with listening for actual MOUSE CLICKS on the text field, while the latter listens for ANY types of focus-gains on it. Thus, when using the TAB key to switch between text fields, only the second solution would perform correctly.

Priidu Neemre
  • 2,813
  • 2
  • 39
  • 40
  • 2
    And this will fail miserably when the user tabs into the field. Nope. – Hovercraft Full Of Eels Jan 08 '15 at 16:05
  • @HovercraftFullOfEels: Yes, thanks for pointing that out. I haven't used the Swing libraries for a while so the issue you mentioned didn't spring to mind right away. I have revised my answer to reflect your suggestions. – Priidu Neemre Jan 08 '15 at 17:03
  • 1
    The problem with this approach is that you always clear the text when the component gains focus. You have no way of determining whether the text is the "prompt" or the "user entered text". – camickr Jan 08 '15 at 17:12
  • @camickr: True, that would mean you'd also need a hard-coded default string to check against each time the event is triggered, which could be problematic for a whole lot of reasons (i18n, "what if the default string is what I wanted to type?!" etc.) – Priidu Neemre Jan 08 '15 at 17:19