2009-11-15 105 views
36

Me gustaría agregar un valor de sugerencia a mi JTextField. Debería verse como la representación de Firefox de <input type="text" title="bla">. Esto crea un campo de edición con el texto 'bla' en el fondo. Si el cuadro de texto tiene foco, el texto del título desaparece y simplemente reaparece si el usuario abandona el cuadro de edición sin texto.Java JTextField con sugerencia de entrada

¿Hay un componente oscilante (libre) que hace algo como esto?

+0

me encontré con un error de oscilación repor t sobre esto en https://swingx.dev.java.net/issues/show_bug.cgi?id=306 Gracias por su ayuda. – Wienczny

+0

2018 y ninguna solución de una línea.Smh –

Respuesta

3

Para cualquier componente Swing (es decir, cualquier elemento que amplíe JComponent), puede llamar al método setToolTipText (String).

Para obtener más información, hacer referencia a los siguientes enlaces:

+5

Creo que no está hablando de información sobre herramientas, quiere algo como "Escriba aquí para buscar" el texto gris que desaparece cuando uno comienza a escribir – Dmitry

+0

Hmm, puede que tenga razón, pero que encaja con el HTML que proporcionó. OP .. si está buscando borrar/configurar el texto predeterminado cuando la entrada está enfocada/borrosa, busque en FocusListener: http://java.sun.com/docs/books/tutorial/uiswing/events/focuslistener.html – Matt

+0

Dmitry tiene razón. Gracias por tu ayuda. – Wienczny

50

Usted puede crear su propia:

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 
import javax.swing.*; 

public class Main { 

    public static void main(String[] args) { 

    final JFrame frame = new JFrame(); 

    frame.setLayout(new BorderLayout()); 

    final JTextField textFieldA = new HintTextField("A hint here"); 
    final JTextField textFieldB = new HintTextField("Another hint here"); 

    frame.add(textFieldA, BorderLayout.NORTH); 
    frame.add(textFieldB, BorderLayout.CENTER); 
    JButton btnGetText = new JButton("Get text"); 

    btnGetText.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
     String message = String.format("textFieldA='%s', textFieldB='%s'", 
      textFieldA.getText(), textFieldB.getText()); 
     JOptionPane.showMessageDialog(frame, message); 
     } 
    }); 

    frame.add(btnGetText, BorderLayout.SOUTH); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
    frame.pack(); 
    } 
} 

class HintTextField extends JTextField implements FocusListener { 

    private final String hint; 
    private boolean showingHint; 

    public HintTextField(final String hint) { 
    super(hint); 
    this.hint = hint; 
    this.showingHint = true; 
    super.addFocusListener(this); 
    } 

    @Override 
    public void focusGained(FocusEvent e) { 
    if(this.getText().isEmpty()) { 
     super.setText(""); 
     showingHint = false; 
    } 
    } 
    @Override 
    public void focusLost(FocusEvent e) { 
    if(this.getText().isEmpty()) { 
     super.setText(hint); 
     showingHint = true; 
    } 
    } 

    @Override 
    public String getText() { 
    return showingHint ? "" : super.getText(); 
    } 
} 

Si todavía estás en Java 1.5, reemplace el this.getText().isEmpty() con this.getText().length() == 0.

+0

Esta solución también es agradable. Debería sobrecargar getText() y filtrar el texto de sugerencia. – Wienczny

+1

Prefiero usar una bandera en getText() que indica si una sugerencia se muestra actualmente o no.De lo contrario, si el usuario ingresa el texto de sugerencia, getText() devolverá una cadena vacía también. –

+0

@MichaelJess, sí, tienes razón. Edité mi ejemplo para incluir una bandera booleana en su lugar. –

13

Aquí es una solución de copia única clase/pegar:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 

import javax.swing.plaf.basic.BasicTextFieldUI; 
import javax.swing.text.JTextComponent; 


public class HintTextFieldUI extends BasicTextFieldUI implements FocusListener { 

    private String hint; 
    private boolean hideOnFocus; 
    private Color color; 

    public Color getColor() { 
     return color; 
    } 

    public void setColor(Color color) { 
     this.color = color; 
     repaint(); 
    } 

    private void repaint() { 
     if(getComponent() != null) { 
      getComponent().repaint();   
     } 
    } 

    public boolean isHideOnFocus() { 
     return hideOnFocus; 
    } 

    public void setHideOnFocus(boolean hideOnFocus) { 
     this.hideOnFocus = hideOnFocus; 
     repaint(); 
    } 

    public String getHint() { 
     return hint; 
    } 

    public void setHint(String hint) { 
     this.hint = hint; 
     repaint(); 
    } 
    public HintTextFieldUI(String hint) { 
     this(hint,false); 
    } 

    public HintTextFieldUI(String hint, boolean hideOnFocus) { 
     this(hint,hideOnFocus, null); 
    } 

    public HintTextFieldUI(String hint, boolean hideOnFocus, Color color) { 
     this.hint = hint; 
     this.hideOnFocus = hideOnFocus; 
     this.color = color; 
    } 

    @Override 
    protected void paintSafely(Graphics g) { 
     super.paintSafely(g); 
     JTextComponent comp = getComponent(); 
     if(hint!=null && comp.getText().length() == 0 && (!(hideOnFocus && comp.hasFocus()))){ 
      if(color != null) { 
       g.setColor(color); 
      } else { 
       g.setColor(comp.getForeground().brighter().brighter().brighter());    
      } 
      int padding = (comp.getHeight() - comp.getFont().getSize())/2; 
      g.drawString(hint, 2, comp.getHeight()-padding-1);   
     } 
    } 

    @Override 
    public void focusGained(FocusEvent e) { 
     if(hideOnFocus) repaint(); 

    } 

    @Override 
    public void focusLost(FocusEvent e) { 
     if(hideOnFocus) repaint(); 
    } 
    @Override 
    protected void installListeners() { 
     super.installListeners(); 
     getComponent().addFocusListener(this); 
    } 
    @Override 
    protected void uninstallListeners() { 
     super.uninstallListeners(); 
     getComponent().removeFocusListener(this); 
    } 
} 

utilizar de esta manera:

TextField field = new JTextField(); 
field.setUI(new HintTextFieldUI("Search", true)); 

Tenga en cuenta que lo que está sucediendo en protected void paintSafely(Graphics g).

+0

¿Cómo se puede hacer para que la pista esté en cursiva, pero el usuario el texto ingresado no es? –

+0

En 'paintSafely()', tendría que llamar a 'setFont (fontHint)' o 'setFont (fontOriginal)' de acuerdo con si 'getText(). IsEmpty()', donde 'fontHint' se habría derivado del original 'getFont()' en el constructor. También tuve que anular 'setFont()' para regenerarlo: 'fontOriginal = getFont(); hintFont = new Font (fontOriginal.getName(), fontOriginal.getStyle() | Font.ITALIC, fontOriginal.getSize()); ' Tenga en cuenta que no utilicé' font.deriveFont() 'porque parece que se come una gran cantidad de memoria y nunca la devuelve ... – Matthieu

+0

funciona como un amuleto, gracias! – patrickdamery

2

Si todavía busca una solución, aquí está uno que combina otras respuestas (Bart Kiers y culmat) para su referencia:

import javax.swing.*; 
import javax.swing.text.JTextComponent; 
import java.awt.*; 
import java.awt.event.FocusEvent; 
import java.awt.event.FocusListener; 


public class HintTextField extends JTextField implements FocusListener 
{ 

    private String hint; 

    public HintTextField() 
    { 
     this(""); 
    } 

    public HintTextField(final String hint) 
    { 
     setHint(hint); 
     super.addFocusListener(this); 
    } 

    public void setHint(String hint) 
    { 
     this.hint = hint; 
     setUI(new HintTextFieldUI(hint, true)); 
     //setText(this.hint); 
    } 


    public void focusGained(FocusEvent e) 
    { 
     if(this.getText().length() == 0) 
     { 
      super.setText(""); 
     } 
    } 

    public void focusLost(FocusEvent e) 
    { 
     if(this.getText().length() == 0) 
     { 
      setHint(hint); 
     } 
    } 

    public String getText() 
    { 
     String typed = super.getText(); 
     return typed.equals(hint)?"":typed; 
    } 
} 

class HintTextFieldUI extends javax.swing.plaf.basic.BasicTextFieldUI implements FocusListener 
{ 

    private String hint; 
    private boolean hideOnFocus; 
    private Color color; 

    public Color getColor() 
    { 
     return color; 
    } 

    public void setColor(Color color) 
    { 
     this.color = color; 
     repaint(); 
    } 

    private void repaint() 
    { 
     if(getComponent() != null) 
     { 
      getComponent().repaint(); 
     } 
    } 

    public boolean isHideOnFocus() 
    { 
     return hideOnFocus; 
    } 

    public void setHideOnFocus(boolean hideOnFocus) 
    { 
     this.hideOnFocus = hideOnFocus; 
     repaint(); 
    } 

    public String getHint() 
    { 
     return hint; 
    } 

    public void setHint(String hint) 
    { 
     this.hint = hint; 
     repaint(); 
    } 

    public HintTextFieldUI(String hint) 
    { 
     this(hint, false); 
    } 

    public HintTextFieldUI(String hint, boolean hideOnFocus) 
    { 
     this(hint, hideOnFocus, null); 
    } 

    public HintTextFieldUI(String hint, boolean hideOnFocus, Color color) 
    { 
     this.hint = hint; 
     this.hideOnFocus = hideOnFocus; 
     this.color = color; 
    } 


    protected void paintSafely(Graphics g) 
    { 
     super.paintSafely(g); 
     JTextComponent comp = getComponent(); 
     if(hint != null && comp.getText().length() == 0 && (!(hideOnFocus && comp.hasFocus()))) 
     { 
      if(color != null) 
      { 
       g.setColor(color); 
      } 
      else 
      { 
       g.setColor(Color.gray); 
      } 
      int padding = (comp.getHeight() - comp.getFont().getSize())/2; 
      g.drawString(hint, 5, comp.getHeight() - padding - 1); 
     } 
    } 


    public void focusGained(FocusEvent e) 
    { 
     if(hideOnFocus) repaint(); 

    } 


    public void focusLost(FocusEvent e) 
    { 
     if(hideOnFocus) repaint(); 
    } 

    protected void installListeners() 
    { 
     super.installListeners(); 
     getComponent().addFocusListener(this); 
    } 

    protected void uninstallListeners() 
    { 
     super.uninstallListeners(); 
     getComponent().removeFocusListener(this); 
    } 
} 



Usage: 
HintTextField field = new HintTextField(); 
field.setHint("Here's a hint"); 
9

que aquí hay una forma sencilla que se ve bien en cualquier L & F:

public class HintTextField extends JTextField { 
    public HintTextField(String hint) { 
     _hint = hint; 
    } 
    @Override 
    public void paint(Graphics g) { 
     super.paint(g); 
     if (getText().length() == 0) { 
      int h = getHeight(); 
      ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
      Insets ins = getInsets(); 
      FontMetrics fm = g.getFontMetrics(); 
      int c0 = getBackground().getRGB(); 
      int c1 = getForeground().getRGB(); 
      int m = 0xfefefefe; 
      int c2 = ((c0 & m) >>> 1) + ((c1 & m) >>> 1); 
      g.setColor(new Color(c2, true)); 
      g.drawString(_hint, ins.left, h/2 + fm.getAscent()/2 - 2); 
     } 
    } 
    private final String _hint; 
} 
+1

Me gusta esto porque la habilidad de sugerencia se convierte en una característica del 'JTextField' en lugar de un complemento externo (que es el caso de la mayoría de las otras soluciones que he visto). Pero tal vez deberías explicar un poco más lo que hace el código y por qué funciona. Hay algún efecto secundario ? ¿Qué garantías tendrá la pista en la fuente que usa el campo? – peterh

3

tienen mirada en WebLookAndFeel en https://github.com/mgarin/weblaf/

WebTextField txtName = new com.alee.laf.text.WebTextField(); 

txtName.setHideInputPromptOnFocus(false); 

txtName.setInputPrompt("Name"); 

txtName.setInputPromptFont(new java.awt.Font("Ubuntu", 0, 18)); 

txtName.setInputPromptForeground(new java.awt.Color(102, 102, 102)); 

txtName.setInputPromptPosition(0); 
+0

Hay muchas otras características compatibles con WebLAF – user2473015

Cuestiones relacionadas