透かし文字付きJTextField(少し改良)

 

人のプログラムというのは、なかなか理解しにくいものです。
でも、何度も繰り返し眺めていると、次第にわかってくるものです。

毎度、管理人イガジーです。

ある処理をする方法は1通りとは限らず、色々な方法があります。
人によって、考え方やコーディングスタイルが違うので、
書いた人の思考回路がわかるまでにどうしても時間がかかるのですね。

と、人のコードを見てあらためて思いました。
人のコード見て、我がコード直せ(?)
イガジーのコードもきっと他の人には分かりにくいんだろうなぁ。

そんな訳で、透かし文字付きのJTextFiled というのを作ってみました。
透かし文字、と言いますか、薄い文字でガイド(ヘルプ)メッセージを出す
テキストフィールドです。↓こういう感じのものです。

作ったのは、2種類ありまして、ひとつはグラフィックで透かし文字を
描いています。もうひとつは、テキストです。

テキストの方が簡単で、汎用性が高いのですが、
フォーカスが当たった時に、透かし文字(ガイドメッセージ)が消えてしまいます。
フォーカスが当たっても文字を入力するまでは透かし文字を表示し続けたい。
ということで、グラフィック版を作りました。
(でも、未入力状態ではカーソルが点滅しないんです。
グラフィックで縦棒を書いているだけなので。。。)

# 改良しました。setOpaque() を使うと解決できました。
コードは次のような感じです。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class GraphicBG {
	JFrame f0;
	JTextFg tf1;
	JTextFt tf2;

	GraphicBG(){ // constructor
		f0=new JFrame("Example");
		f0.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JPanel p0=new JPanel(new GridLayout(3,1));
		JLabel lb=new JLabel("透かし文字付きJTextField");
		p0.add(lb);

		tf1=new JTextFg("ここに入力してね");
		p0.add(tf1);

		tf2=new JTextFt("Please input here.");
		p0.add(tf2);

		f0.add(p0,BorderLayout.CENTER);
		f0.setSize(200,100);
		f0.setVisible(true);
	} // constructor

	public static void main(String[] args) {
		new GraphicBG();
	}
	class JTextFg extends JTextField { implements FocusListener { //
		private static final long serialVersionUID = 1L;
		Color cur=Color.GRAY;
		BufferedImage bi=new BufferedImage(300,20,BufferedImage.TYPE_INT_RGB);
		JTextFg(String msg){
			Graphics g0=bi.getGraphics();
			g0.setColor(Color.WHITE);
			g0.fillRect(0, 0, bi.getWidth(), bi.getHeight());
			g0.setColor(Color.LIGHT_GRAY);
			g0.setFont(new Font(Font.DIALOG,Font.BOLD,12));
			g0.drawString(msg,8,15);
//			this.addFocusListener(this);
		}
/*
		@Override public void focusGained(FocusEvent e) {
			cur=Color.BLACK;
			repaint();
		}
		@Override public void focusLost(FocusEvent e) {
			cur=Color.WHITE;
			repaint();
		}
*/
		@Override public void paintComponent(Graphics g) {
			if (getText().trim().isEmpty()) {
				this.setOpaque(false); // 追加★
				g.drawImage(bi, 0, 0, null);
//				g.setColor(cur);
//				g.fillRect(3, 4, 1, 16);
			}else{
				super.paintComponent(g);
				this.setOpaque(true);
			}
			super.paintComponent(g); // つねに実行するように変更
		}
	}

	class JTextFt extends JTextField implements FocusListener {
		private static final long serialVersionUID = 1L;
		String helpmsg;
		String bakstr="";
		JTextFt(String msg){
			helpmsg=msg;
			addFocusListener(this);
			drawmsg();
		}
		void drawmsg() {
			setForeground(Color.LIGHT_GRAY);
			setText(helpmsg);
		}
		@Override
		public void focusGained(FocusEvent arg0) {
			setForeground(Color.BLACK);
			setText(bakstr);
		}
		@Override
		public void focusLost(FocusEvent arg0) {
			bakstr=getText();
			if (bakstr.equals("")) {
				drawmsg();
			}
		}
	}
}

最初のJTextFg tf1;(上段)がグラフィック版です。
下段のJTextFt tf2;の方が、テキスト版です。
使い方は、
JTextFg tfg=new JTextFg("透かし文字");JTextFt tft=new JTextFt("透かし文字");と、透かし文字列を指定するだけで、
あとは、JTextFieldと同じです。
(グラフィック版は、文字サイズ等を決め打ちしているのでご注意)
# グラフィック版の paintComponent()内の、else { this.setOpaque(false);} を削除すると
透かしを表示し続けることができます。

透かし(薄い)色として、Color.LIGHT_GRAY を使っていますが
そのあたりはお好みで変えてください。

ご質問やご要望などはお気軽にメールフォームからどうぞ。

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)