• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:JPasswordFieldにヒント文字列を描画する
#navi(../)
#tags(JPasswordField, TextLayout, Focus)
RIGHT:Posted by &author(aterai); at 2012-06-04
*JPasswordFieldにヒント文字列を描画する [#cec5d8dc]
``JPasswordField``に入力がない場合、ヒント文字列を描画します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(https://lh3.googleusercontent.com/-UKh7dosDsR4/T8xFLnpMGwI/AAAAAAAABNY/nxgzH2XN1vo/s800/InputHintPasswordField.png)

**サンプルコード [#c9574319]
#code(link){{
class WatermarkPasswordField extends JPasswordField
                             implements FocusListener, DocumentListener {
  private boolean showWatermark = true;
  public WatermarkPasswordField() {
    super();
    addFocusListener(this);
    getDocument().addDocumentListener(this);
  }
  @Override public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if(showWatermark) {
      Graphics2D g2 = (Graphics2D)g.create();
      Insets i = getInsets();
      Font font = getFont();
      FontRenderContext frc = g2.getFontRenderContext();
      TextLayout tl = new TextLayout("Password", font, frc);
      g2.setPaint(hasFocus()?Color.GRAY:Color.BLACK);
      int baseline = getBaseline(getWidth(), getHeight());
      tl.draw(g2, i.left+1, baseline);
      g2.dispose();
    }
  }
  @Override public void focusGained(FocusEvent e) {
    repaint();
  }
  @Override public void focusLost(FocusEvent e) {
    showWatermark = getPassword().length==0;
    repaint();
  }
  @Override public void insertUpdate(DocumentEvent e) {
    showWatermark = e.getDocument().getLength()==0;
    repaint();
  }
  @Override public void removeUpdate(DocumentEvent e) {
    showWatermark = e.getDocument().getLength()==0;
    repaint();
  }
  @Override public void changedUpdate(DocumentEvent e) {}
}
}}

**解説 [#gd45f72d]
上記のサンプルでは、``JPasswordField#paintComponent(...)``をオーバーライドしてヒント文字列を描画しています。

``paintComponent(...)``メソッドをオーバーライドするのは同じですが、[[JTextFieldに透かし画像を表示する>Swing/WatermarkInTextField]]とは異なり、``JPasswordField``にフォーカスがあっても、まだ入力がない場合(DocumentListenerを追加)などに、ヒント文字列を非表示にはせず、薄く表示するようにしています(参考: [http://tips4java.wordpress.com/2009/11/29/text-prompt/ Text Prompt « Java Tips Weblog])。

**参考リンク [#rc33439c]
- [http://tips4java.wordpress.com/2009/11/29/text-prompt/ Text Prompt « Java Tips Weblog]
-- ``JTextComponent``に``BorderLayout``を設定して、文字列やアイコンを設定したJLabelを追加し、これを``JLabel#setVisible(boolean)``で切り替えているので、汎用的に使用することができます。

- [[JTextFieldにフォーカスと文字列が無い場合の表示>Swing/GhostText]]
-- ``setText()``を使用

- [[JTextFieldに透かし画像を表示する>Swing/WatermarkInTextField]]
-- ``paintComponent(...)``メソッドをオーバーライド

**コメント [#w04b195a]
#comment