How to display faint gray “ghost text” in a JTextField?

后端 未结 2 372
长发绾君心
长发绾君心 2020-12-01 12:39

I don\'t know if I got the right name for it, but I\'m looking to see if there is a specific way to implement a text field so that while it doesn\'t have focus and is empty,

相关标签:
2条回答
  • 2020-12-01 12:58

    Thank you very much Guillaume, this is very good!

    I just changed a few things for ease of use:

    1. used JTextComponent instead of JTextField so it works with all text inputs
    2. took out the test class and made it public and non-static to make it stand-alone

    Here is the code:

    import java.awt.Color;
    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.JTextComponent;
    
    public class GhostText implements FocusListener, DocumentListener, PropertyChangeListener
    {
        private final JTextComponent textComp;
        private boolean isEmpty;
        private Color ghostColor;
        private Color foregroundColor;
        private final String ghostText;
    
        public GhostText(final JTextComponent textComp, String ghostText)
        {
            super();
            this.textComp = textComp;
            this.ghostText = ghostText;
            this.ghostColor = Color.LIGHT_GRAY;
            textComp.addFocusListener(this);
            registerListeners();
            updateState();
            if (!this.textComp.hasFocus())
            {
                focusLost(null);
            }
        }
    
        public void delete()
        {
            unregisterListeners();
            textComp.removeFocusListener(this);
        }
    
        private void registerListeners()
        {
            textComp.getDocument().addDocumentListener(this);
            textComp.addPropertyChangeListener("foreground", this);
        }
    
        private void unregisterListeners()
        {
            textComp.getDocument().removeDocumentListener(this);
            textComp.removePropertyChangeListener("foreground", this);
        }
    
        public Color getGhostColor()
        {
            return ghostColor;
        }
    
        public void setGhostColor(Color ghostColor)
        {
            this.ghostColor = ghostColor;
        }
    
        private void updateState()
        {
            isEmpty = textComp.getText().length() == 0;
            foregroundColor = textComp.getForeground();
        }
    
        @Override
        public void focusGained(FocusEvent e)
        {
            if (isEmpty)
            {
                unregisterListeners();
                try
                {
                    textComp.setText("");
                    textComp.setForeground(foregroundColor);
                }
                finally
                {
                    registerListeners();
                }
            }
    
        }
    
        @Override
        public void focusLost(FocusEvent e)
        {
            if (isEmpty)
            {
                unregisterListeners();
                try
                {
                    textComp.setText(ghostText);
                    textComp.setForeground(ghostColor);
                }
                finally
                {
                    registerListeners();
                }
            }
        }
    
        @Override
        public void propertyChange(PropertyChangeEvent evt)
        {
            updateState();
        }
    
        @Override
        public void changedUpdate(DocumentEvent e)
        {
            updateState();
        }
    
        @Override
        public void insertUpdate(DocumentEvent e)
        {
            updateState();
        }
    
        @Override
        public void removeUpdate(DocumentEvent e)
        {
            updateState();
        }
    
    }
    
    0 讨论(0)
  • 2020-12-01 13:21

    For what it's worth, I found it interesting to actually implement it, so I thought to share it with you (I am not looking for votes).

    It's really non-invasive since all you have to do is call new GhostText(textField, "Please enter some text here...");. The rest of the code is only to make it run.

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    
    public class Test {
    
        public static class GhostText implements FocusListener, DocumentListener, PropertyChangeListener {
            private final JTextField textfield;
            private boolean isEmpty;
            private Color ghostColor;
            private Color foregroundColor;
            private final String ghostText;
    
            protected GhostText(final JTextField textfield, String ghostText) {
                super();
                this.textfield = textfield;
                this.ghostText = ghostText;
                this.ghostColor = Color.LIGHT_GRAY;
                textfield.addFocusListener(this);
                registerListeners();
                updateState();
                if (!this.textfield.hasFocus()) {
                    focusLost(null);
                }
            }
    
            public void delete() {
                unregisterListeners();
                textfield.removeFocusListener(this);
            }
    
            private void registerListeners() {
                textfield.getDocument().addDocumentListener(this);
                textfield.addPropertyChangeListener("foreground", this);
            }
    
            private void unregisterListeners() {
                textfield.getDocument().removeDocumentListener(this);
                textfield.removePropertyChangeListener("foreground", this);
            }
    
            public Color getGhostColor() {
                return ghostColor;
            }
    
            public void setGhostColor(Color ghostColor) {
                this.ghostColor = ghostColor;
            }
    
            private void updateState() {
                isEmpty = textfield.getText().length() == 0;
                foregroundColor = textfield.getForeground();
            }
    
            @Override
            public void focusGained(FocusEvent e) {
                if (isEmpty) {
                    unregisterListeners();
                    try {
                        textfield.setText("");
                        textfield.setForeground(foregroundColor);
                    } finally {
                        registerListeners();
                    }
                }
    
            }
    
            @Override
            public void focusLost(FocusEvent e) {
                if (isEmpty) {
                    unregisterListeners();
                    try {
                        textfield.setText(ghostText);
                        textfield.setForeground(ghostColor);
                    } finally {
                        registerListeners();
                    }
                }
            }
    
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                updateState();
            }
    
            @Override
            public void changedUpdate(DocumentEvent e) {
                updateState();
            }
    
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateState();
            }
    
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateState();
            }
    
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    init();
                }
            });
        }
    
        public static void init() {
            JFrame frame = new JFrame("Test ghost text");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel panel = new JPanel();
            JTextField textField = new JTextField();
            JButton button = new JButton("Grab focus");
            GhostText ghostText = new GhostText(textField, "Please enter some text here...");
            textField.setPreferredSize(new Dimension(300, 24));
            panel.add(textField);
            panel.add(button);
            frame.add(panel);
            frame.pack();
            frame.setVisible(true);
            button.grabFocus();
        }
    }
    
    0 讨论(0)
提交回复
热议问题