---
category: swing
folder: InputHintPasswordField
title: JPasswordFieldにヒント文字列を描画する
tags: [JPasswordField, TextLayout, Focus]
author: aterai
pubdate: 2012-06-04T14:33:56+09:00
description: JPasswordFieldに入力がない場合、ヒント文字列を描画します。
image: https://lh3.googleusercontent.com/-UKh7dosDsR4/T8xFLnpMGwI/AAAAAAAABNY/nxgzH2XN1vo/s800/InputHintPasswordField.png
---
* 概要 [#summary]
`JPasswordField`に入力がない場合、ヒント文字列を描画します。

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

* サンプルコード [#sourcecode]
#code(link){{
class WatermarkPasswordField extends JPasswordField
                             implements FocusListener, DocumentListener {
  private boolean showWatermark = true;
  public WatermarkPasswordField() {
    super();
    addFocusListener(this);
    getDocument().addDocumentListener(this);
  }

  @Override protected 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) {}
}
}}

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

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

* 参考リンク [#reference]
- [https://tips4java.wordpress.com/2009/11/29/text-prompt/ Text Prompt « Java Tips Weblog]
-- `JTextComponent`に`BorderLayout`を設定して文字列やアイコンを設定した`JLabel`を追加し、これを`JLabel#setVisible(boolean)`で切り替えているので汎用的な使用が可能
- [[JTextFieldにフォーカスと文字列が無い場合の表示>Swing/GhostText]]
-- `JTextField#setText()`メソッドを使用
- [[JTextFieldに透かし画像を表示する>Swing/WatermarkInTextField]]
-- `JTextField#paintComponent(...)`メソッドをオーバーライド
- [[JComboBoxでアイテムが選択されていない場合のプレースホルダ文字列を設定する>Swing/ComboBoxPlaceholder]]

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