でか文字表示ツールを作ってみよう3

   2012/07/08

いきなり汎用的な(抽象化した)コードを書こうとして行き詰まるよりは
まずは具体的なコードを書いてみるのが近道です。

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

ですから、堂々とハリボテ(見かけだけ)のプログラムを書いてみましょう。
その具体的なコードから、ひとつひとつ一般化してゆけばよいのです。
という訳で、実際に入力された文字やサイズに応じて、文字を描画する
一般化されたメソッドを作ります。
元にするのは、ハリボテの次のコードです。

// ハリボテ(決め打ち)のコード
cv.g.setColor(Color.WHITE);
cv.g.fillRect(0, 0, gbWIDTH, gbHEIGHT); // バッファ全体をクリア
cv.g.setFont(new Font(Font.SERIF,Font.PLAIN,300));
cv.g.setColor(Color.BLACK);
cv.g.drawString("漢", 0, 300);

この、表示している文字”漢”の部分を、TextField ch から得てくるようにします。
"漢" → ch.getText();同様に、300 の部分をTextField sz から得るようにするのですが
TextFieldから得られるのは文字なので、数値に変換します。
あわせて、変な入力(数字以外の入力)や、最大最小の範囲チェックも
行う文字数値変換メソッドを作っておきましょう。

int getnum(TextField tf, int def,int min, int max) {
	int r=def;
	try {
		r=Integer.parseInt(tf.getText());
	}catch (Exception e) {
		r=def;
	}
	if (r<min) {
		r=min;
	}else if (r>max) {
		r=max;
	}
	tf.setText(Integer.toString(r));
	return r;
}

引数の def は、異常値(数字以外等)の時にセットする値で
minは 最小値、max は最大値で、その範囲に丸め込むようにしています。
tf.setText(Integer.toString(r));は、丸め込みなどの結果を表示にフィードバックするための処理です。
Choice fsel から、選ばれているものを得るには
fsel.getSelectedItem()とします。

これらを使って、文字を描画するメソッドは次のような感じになります。

void drawChar() {
	int fsize=getnum(sz,300,14,340);
	cv.g.setColor(Color.WHITE); // 白で
	cv.g.fillRect(0, 0, gbWIDTH, gbHEIGHT);  // バッファをクリア
	cv.g.setFont(new Font(fsel.getSelectedItem(),Font.PLAIN,fsize));
	cv.g.setColor(Color.BLACK);
	cv.g.drawString(ch.getText(), 0, fsize);
	cv.repaint(); //再描画
}

最後のcv.repaint()は再描画のおまじないです。

さて、この文字描画メソッドは、いつ動作するようにしましょうか?
・TextFiled ch に文字が入力されたら
・Choice fsel でフォントが選ばれたら
・TextFiled ch にサイズが入力されたら
が自然ですね。
TextFiled に入力が行われた事を検出したいのですが、
入力の「完了」となるイベントは、[Enter]キーを押した時に発生します。
すなわち、300 を 200 に書き換えただけではそれを検出できず
[Enter]が押されてはじめて処理が行えるのです。
実際に、TextFieldにActionListenerを組み込んで試してみてください。

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

class BigFont2 extends Frame implements ActionListener {
	private static final long serialVersionUID = 1L;
	final int gbWIDTH=800,gbHEIGHT=400;
	MyCanvas cv;
	Choice fsel=new Choice();
	TextField ch,sz;

	BigFont2() { // constructor
		String [] fontlist={
				"Serif",
				"SansSerif",
				"Monospaced",
				"Meiryo",
				"MS Gothic",
				"MS Mincho",
				"Osaka",
				"VLgothic",
				"IPAGothic",
				"IPAMincho"
			};
		this.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent ev) {
				System.exit(0);
			}
		});
		this.setTitle("でか文字");
		cv=new MyCanvas(gbWIDTH,gbHEIGHT);
		this.add(cv,BorderLayout.CENTER);
		for (int i=0;i<fontlist.length;++i){
			fsel.add(fontlist[i]);
		}
		Panel p0=new Panel();
		p0.add(new Label("文字"));
		ch=new TextField("漢",4);
		ch.addActionListener(this);
		p0.add(ch);
		p0.add(fsel);
		p0.add(new Label("サイズ"));
		sz=new TextField("300",4);
		sz.addActionListener(this);
		p0.add(sz);
		this.add(p0,BorderLayout.NORTH);
		drawChar(); //
		this.setSize(400,440);
		this.setVisible(true);
	}

	int getnum(TextField tf, int def,int min, int max) {
		int r=def;
		try {
			r=Integer.parseInt(tf.getText());
		}catch (Exception e) {
			r=def;
		}
		if (r<min) {
			r=min;
		}else if (r>max) {
			r=max;
		}
		tf.setText(Integer.toString(r));
		return r;
	}

	void drawChar() {
		int fsize=getnum(sz,300,14,340);
		cv.g.setColor(Color.WHITE);
		cv.g.fillRect(0, 0, gbWIDTH, gbHEIGHT);
		cv.g.setFont(new Font(fsel.getSelectedItem(),Font.PLAIN,fsize));
		cv.g.setColor(Color.BLACK);
		cv.g.drawString(ch.getText(), 0, fsize);
		cv.repaint(); //
	}

	public static void main(String[] args) {
		new BigFont2();
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		drawChar();
	}

	class MyCanvas extends Canvas {
		private static final long serialVersionUID = 1L;
		BufferedImage bi;
		Graphics g=null;
		MyCanvas(int ww,int hh) {
			bi=new BufferedImage(ww,hh,BufferedImage.TYPE_INT_RGB);
			g=bi.getGraphics();
		}

		@Override
		public void paint(Graphics g0){
			g0.drawImage(bi, 0, 0, null);
		}
	}
}

[Enter]キーを押すのはイマイチなので、次回はフォーカス移動でも描画する
ようにしてみましょう。フォーカス移動とは、TextFiled以外をクリックして
そのTextField からフォーカスが失われた(別のものにフォーカスが当たった)という
イベントを使います(FocusListenerを組み込みます)。
併せて、Choiceでフォントが選ばれた時も描画するようにしましょう。
Choiceでの選択は、ItemListener を組み込んで検出します。

次回のソースコード例の公開前に、ぜひご自身でコードを書いてみてください。
ご意見、ご質問、リクエストなどは、お気軽にメールフォームからどうぞ。

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

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

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

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