2012-05-08 57 views
16

No sé si obtuve el nombre correcto para ello, pero estoy buscando para ver si hay una manera específica de implementar un campo de texto para que, aunque no tenga el foco y esté vacío, un gris tenue cadena de texto se muestra en el campo. Cuando se hace clic en el campo, el texto debe desaparecer, exactamente como funciona la barra de búsqueda como la de StackOverflow. Sé que puedo cambiar el uso de setForeground() y centrar a los oyentes para lograr esto, pero me preguntaba si alguien sabía de alguna implementación de Java que pudiera manejar esto por mí.¿Cómo se muestra el débil "texto fantasma" gris en un JTextField?

+0

AF AIK, no. Pero me alegraría que me dijeran lo contrario –

+0

Puedo decirle que Swing no proporciona esto de forma nativa (pero alguien puede haber escrito una biblioteca de terceros para hacerlo). –

+2

Esto podría ayudar: http://stackoverflow.com/questions/1738966/java-jtextfield-with-input-hint – Ranga

Respuesta

36

Por lo que vale, me pareció interesante implementarlo, así que pensé en compartirlo contigo (no estoy buscando votos).

Realmente no es invasivo ya que todo lo que tiene que hacer es llamar al new GhostText(textField, "Please enter some text here...");. El resto del código es solo para hacer que se ejecute.

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

* "No estoy buscando votos" * Difícil. +1 Chúpalo. ;) –

+1

Esto puede ser un poco quisquilloso, pero ¿podría lograr esto sin eliminar el texto fantasma hasta que se escriba un carácter? Firefox puede mostrar de lo que estoy hablando: si abres una pestaña nueva, la barra de direcciones tiene un texto fantasma que dice "Buscar o ingresar dirección" que no desaparecerá cuando enfocas el campo, sino que se mantendrá hasta que ingreses el primer personaje. – ryvantage

8

Muchas gracias Guillaume, ¡esto es muy bueno!

acabo de cambiar algunas cosas para facilitar su uso:

  1. utilizado JTextComponent en lugar de JTextField por lo que funciona con todo el texto entradas
  2. llevó a cabo la clase de prueba y lo hizo público y no estático para que sea autónomo

Aquí está el código:

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

cómo comprobar vacío jTextField programmically? Método getText return GhostText: | – do01

+0

Bueno, y es aún mejor si, en el focoLost, agrega esto: else { unregisterListeners(); try { textComp.setForeground (foregroundColor); } finalmente { registerListeners(); } } –

Cuestiones relacionadas