Wednesday, March 18, 2009 / Java

ヒント情報付きテキストフィールド (Java,Swing)

入力フォームに何を入力したらいいか例を示したい場合があります。 フォームの横に例を書く、という単純な方法もありますが、 以下のようにテキストフィールド上にヒントを書くという方法もあります。

textfield-1

もちろん、実際に入力するためにテキストフィールドに フォーカスを持って行ったときには、このヒントは消えます。

textfield-2

このようにすれば、ヒントを表示するスペースを節約できるだけでなく、 わかりやすくすることができます。

HintTextField.java

ヒント情報付きのテキストフィールドを実現するために、 JTextFieldを拡張しています。

拡張したポイントは、 paintComponent()メソッドをオーバーライドした上で…

  1. フォーカスが無いときには、ヒント情報を描画する
  2. テキストフィールドにテキストがセットされている場合は、ヒント情報は描画しない
  3. setHint(String)メソッドでヒント情報を設定

という具合です。

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JTextField;

public class HintTextField extends JTextField{
    private String hint;
    public void setHint(String hint){
       this.hint=hint;
    }

    public String getHint(){
       if(hint==null)
         hint="";
       return hint;
    }

    public void setText(String arg0) {
       super.setText(arg0);
       repaint();
    }

    public HintTextField(){
       super();

       addFocusListener(new FocusListener(){
         public void focusGained(FocusEvent arg0) {
          repaint();
         }
         public void focusLost(FocusEvent arg0) {
          repaint();
         }
       });
    }

    protected void paintComponent(Graphics g) {
       super.paintComponent(g);

       if( hasFocus() ){
         return ;
       }
       if( getText().length()>0 ){
         return ;
       }
       if( getHint().length()<1){
         return ;
       }

       Font oldFont = g.getFont();
       Color oldColor = g.getColor();

       g.setFont(getFont());
       g.setColor(Color.LIGHT_GRAY);

       Insets insets = getBorder().getBorderInsets(this);
       int h = g.getFontMetrics().getAscent();
       g.drawString(getHint(),insets.left,insets.top+h);

       g.setFont(oldFont);
       g.setColor(oldColor);
    }
}

HintTextFieldのテスト用コード

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class Test extends JFrame{
    public Test(){
       super();

       JButton okButton=new JButton(" OK ");
       okButton.requestFocus();

       HintTextField tf1=new HintTextField();
       tf1.setHint("(例)メロンパン");

       HintTextField tf2=new HintTextField();
       tf2.setHint("(例)お寿司");

       HintTextField tf3=new HintTextField();
       tf3.setHint("(例)カレーライス");

       Box box=Box.createVerticalBox();
       box.add(new JLabel("好きな食べ物を3つ書いてください。"));
       box.add(tf1);
       box.add(tf2);
       box.add(tf3);
       box.add(okButton);

       getContentPane().add(box,BorderLayout.NORTH);
    }

    public static void main(String[] args){
       Test t=new Test();
       t.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
       t.pack();
       t.setVisible(true);
    }
}