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

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

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

它真的是非侵入性的,因为你所要做的就是调用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(); } } 

非常感谢Guillaume,这非常好!

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

  1. 使用JTextComponent而不是JTextField,因此它适用于所有文本输入
  2. 取出了测试课程并将其公开和非静态地制作成独立的

这是代码:

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