如何在JTextField中显示微弱的灰色“鬼文本”?

时间:2012-05-08 21:29:15

标签: java swing jtextfield

我不知道我是否得到了正确的名称,但是我想看看是否有一种特定的方法来实现一个文本字段,这样当它没有焦点而且是空的时候,一个微弱的灰色的文本字符串显示在字段中。单击该字段时,文本应该消失,就像StackOverflow的搜索栏一样。我知道我可以改变使用setForeground()并集中监听器来实现这一目标,但我只是想知道是否有人知道某些Java实现可以为我处理这个问题。

2 个答案:

答案 0 :(得分:40)

对于它的价值,我发现实际实现它很有意思,所以我想与你分享(我不是在寻找选票)。

这真的是非侵入性的,因为您所要做的就是致电new GhostText(textField, "Please enter some text here...");。其余的代码只是让它运行。

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();
    }
}

答案 1 :(得分:8)

非常感谢Guillaume,这非常好!

我只是改变了一些东西以方便使用:

  1. 使用JTextComponent而不是JTextField,因此它适用于所有文本 输入
  2. 取出了测试课程并将其公开,非静态,以使其独立
  3. 以下是代码:

    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();
        }
    
    }