2009-11-15 51 views
36

Ich möchte meinem JTextField einen Hinweiswert hinzufügen. Es sollte wie Firefox-Wiedergabe von <input type="text" title="bla"> aussehen. Dies erzeugt ein Bearbeitungsfeld mit dem Text 'bla' im Hintergrund. Wenn das Textfeld den Fokus hat, verschwindet der Titeltext und erscheint wieder, wenn der Benutzer die Editbox ohne Text verlässt.Java JTextField mit Eingabehinweis

Gibt es eine (freie) Schwungkomponente, die so etwas macht?

+0

ich eine Schaukel Bug repor gefunden t über dieses bei https://swingx.dev.java.net/issues/show_bug.cgi?id=306 Danke für Ihre Hilfe. – Wienczny

+0

2018 und keine one-line solution.Smh –

Antwort

16

Werfen Sie einen Blick auf diese: http://code.google.com/p/xswingx/

Es ist nicht sehr schwierig ist, es zu implementieren allein, übrigens. Ein paar Listener und benutzerdefinierte Renderer und voila.

3

Für jede Swing-Komponente (dh alles, was JComponent erweitert) können Sie die setToolTipText (String) -Methode aufrufen.

Für weitere Informationen verweisen die folgenden Links:

+5

Ich denke, er spricht nicht über Tooltip, er möchte etwas wie "Geben Sie hier, um zu suchen" grauen Text, der verschwindet, wenn man beginnt zu tippen – Dmitry

+0

Hmm, Sie könnten Recht haben, aber das passt mit das HTML, das er zur Verfügung gestellt hat. OP .. Wenn Sie Standardtext löschen möchten, wenn die Eingabe fokussiert/unscharf ist, schauen Sie in FocusListener: http://java.sun.com/docs/books/tutorial/uiswing/events/focuslistener.html – Matt

+0

Dmitry hat Recht. Danke für Ihre Hilfe. – Wienczny

50

könnten Sie Ihre eigene Gruppe gründen:

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

Wenn Sie immer noch auf Java 1.5 sind, die this.getText().isEmpty() mit this.getText().length() == 0 ersetzen.

+0

Diese Lösung ist auch nett. Sie müssten getText() überladen und den Hinweistext filtern. – Wienczny

+1

Ich würde lieber eine Flagge in getText() verwenden, die anzeigt, ob ein Hinweis gerade angezeigt wird oder nicht.Andernfalls, wenn der Benutzer zufällig den Hinweistext eingibt, würde getText() auch eine leere Zeichenfolge zurückgeben. –

+0

@MichaelJess, ja, du hast Recht. Ich habe mein Beispiel so bearbeitet, dass stattdessen eine boolesche Flagge eingefügt wurde. –

13

Hier ist eine einzelne Klasse copy/paste-Lösung:

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

es wie folgt verwendet:

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

Beachten Sie, dass es in protected void paintSafely(Graphics g) geschieht.

+0

Wie könnte man es so machen, dass der Hinweis kursiv geschrieben wird, sondern der Benutzer eingegebener Text ist nicht? –

+0

In 'paintSafely()' müßten Sie 'setFont (fontHint)' oder 'setFont (fontOriginal)' aufrufen, je nachdem, ob 'getText(). IsEmpty()' wäre, wobei 'fontHint' von der abgeleitet wäre original 'getFont()' im Konstruktor. Ich musste auch 'setFont() 'überschreiben, um es neu zu generieren: ' fontOriginal = getFont(); HinweisFont = new Font (fontOriginal.getName(), fontOriginal.getStyle() | Font.ITALIC, fontOriginal.getSize()); ' Beachten Sie, dass ich' font.deriveFont() 'nicht verwendet habe, weil es scheint, dass es isst eine Menge Speicher und gibt es nie wieder zurück ... – Matthieu

+0

funktioniert wie ein Charme, danke! – patrickdamery

2

Wenn Sie nach einer Lösung suchen noch, hier ist eine, die anderen Antworten (Bart Kiers und culmat) kombiniert für Ihre Referenz:

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

Hier ist eine einfache Art und Weise, die in jedem L & F sieht gut aus:

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

Ich mag das, weil die Tipp-Fähigkeit ein Feature des 'JTextField' wird und nicht ein externes Add-On (was bei den meisten anderen Lösungen, die ich gesehen habe, der Fall ist). Aber vielleicht solltest du ein bisschen mehr erklären, was der Code macht und warum er funktioniert. Gibt es irgendwelche Nebenwirkungen? Was garantiert, dass es den Hinweis in der Schriftart malt, die das Feld verwendet? – peterh

3

Haben Blick auf WebLookAndFeel bei 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

Es gibt viele andere Funktionen, die von WebLAF unterstützt werden – user2473015