2009-11-15 14 views
36

Vorrei aggiungere un valore suggerimento al mio JTextField. Dovrebbe assomigliare al rendering di Firefox di <input type="text" title="bla">. Questo crea un campo di modifica con il testo "bla" sullo sfondo. Se la casella di testo è attiva, il testo del titolo scompare e riappare solo se l'utente lascia la casella di testo senza testo.Java JTextField con suggerimento di input

C'è un componente swing (gratuito) che fa qualcosa di simile?

+0

ho trovato un bug RELAZIONE altalena t su questo a https://swingx.dev.java.net/issues/show_bug.cgi?id=306 Grazie per il vostro aiuto. – Wienczny

+0

2018 e nessuna soluzione a una riga. –

risposta

3

Per qualsiasi componente di Swing (ovvero, qualsiasi cosa estenda JComponent), è possibile chiamare il metodo setToolTipText (String).

Per ulteriori informazioni, fare riferimento ai seguenti link:

+5

Penso che non stia parlando di tooltip, vuole qualcosa tipo "Digita qui per cercare" testo grigio che scompare quando si inizia a digitare – Dmitry

+0

Hmm, potresti avere ragione, ma che si adattava l'HTML che ha fornito. OP .. se stai cercando di cancellare/impostare il testo predefinito quando l'input è focalizzato/sfocato, guarda in FocusListener: http://java.sun.com/docs/books/tutorial/uiswing/events/focuslistener.html – Matt

+0

Dmitry ha ragione. Grazie per l'aiuto. – Wienczny

50

Si potrebbe creare il proprio:

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

Se siete ancora in Java 1.5, sostituire il this.getText().isEmpty() con this.getText().length() == 0.

+0

Anche questa soluzione è buona. Dovresti sovraccaricare getText() e filtrare il testo di suggerimento. – Wienczny

+1

Preferisco usare un flag in getText() che indica se un suggerimento è attualmente mostrato o meno.Altrimenti, se l'utente dovesse inserire il testo del suggerimento, getText() restituirebbe anche una stringa vuota. –

+0

@ Michaeljess, sì, hai ragione. Ho modificato il mio esempio per includere invece un flag booleano. –

13

Ecco una soluzione singola classe copia/incolla:

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

usare in questo modo:

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

Nota che sta accadendo in protected void paintSafely(Graphics g).

+0

Come si può fare in modo che il suggerimento sia in corsivo ma l'utente il testo inserito non è? –

+0

Nel 'paintSafely()', dovresti chiamare 'setFont (fontHint)' o 'setFont (fontOriginal)' a seconda che sia 'getText(). IsEmpty()', dove 'fontHint' sarebbe stato derivato dal 'getFont()' originale nel costruttore. Ho anche dovuto sovrascrivere 'setFont()' per rigenerarlo: 'fontOriginal = getFont(); hintFont = new Font (fontOriginal.getName(), fontOriginal.getStyle() | Font.ITALIC, fontOriginal.getSize()); ' Nota che non ho usato' font.deriveFont() 'perché sembra che mangia un sacco di memoria e non lo restituisce mai ... – Matthieu

+0

funziona come un incantesimo, grazie! – patrickdamery

2

Se ancora cercare una soluzione, ecco uno che ha combinato altre risposte (Bart autoclavi e culmat) per il vostro riferimento:

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

Ecco un modo semplice che guarda bene in qualsiasi 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

Mi piace perché l'abilità suggerimento diventa una caratteristica del 'JTextField' piuttosto che un add-on esterno (che è il caso della maggior parte delle altre soluzioni che ho visto). Ma forse dovresti spiegare un po 'di più cosa fa il codice e perché funziona. Ci sono effetti collaterali? Cosa garantisce che dipingerà il suggerimento nel carattere che il campo utilizza? – peterh

3

Abbia un'occhiata a WebLookAndFeel al 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

Ci sono molte altre funzionalità supportate da WebLAF – user2473015

Problemi correlati