16進電卓を作ってみよう4

   2012/05/08

Listener というのを辞書で見ると「聞く人」「聴取者」という意味が
書いてありますが、Javaプログラミングで出てくる ActionListener や
ItemListener などは、ちょっと違う意味になります。

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

そうですね、我流の訳をつけると Javaプログラミングでの Listener とは
「(使う人の)操作に応じた処理(をするプログラム)」という意味です。
Listen には、(操作されるまで)「スタンばる/聞き耳をたてる」という
意味合いがあるのでしょう。

そして、btn.addActionListener(new ClassName()); というのは
操作に応じた処理(をするプログラム)の「登録」です。
addActionListener(); した時に実行されるのではなくて、
(ボタンなどが)押された時に実行されます。

長いスペルですが、Eclipseを使えば、addA まで押して補完キー
(Windowsの場合は CTRL+スペース、Linuxの場合は CTRL+/)
を押すと、あら不思議、addActionListener と、決まり文句が挿入されて便利です。

ラジオボタン(Checkbox)の場合は、ActionListener ではなく
ItemListener という名称になっています。
なぜかは知りませんが、そうなっているので、観念しましょう。

ItemListener は、例えば次のようなクラスになります。

class setRadix implements ItemListener {
	@Override
	public void itemStateChanged(ItemEvent e) {
		if (hx.getState()) radix=16;
		else radix=10;
		display();
	}
}

登録する関数は itemStateChanged() で
チェックされた時に呼び出されます(「コールバックされる」とも言います)。

dec(10進選択のチェックボックス)とHEX(16進選択トのチェックボックス)で
別々の ItemListener を登録しても良いのですが、類似処理になるので
getState() で選択状態をチェックして、radixをセットし、それ以外は
同じ処理にしています(好き好きです)。

この ItemListener を

	hx.addItemListener(new setRadix());
	dc.addItemListener(new setRadix());

として組み込みます。

もうひとつ、クリアキーの処理も入れましょう。

for (int i=0;i<20;++i) {
	if (fn[i]>=0) btn[i]=new nBtn(lb[i],fn[i]);
	else {
		btn[i]=new Button(lb[i]);
		if (fn[i]==KCLR) {
			btn[i].addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					result=0;display();
				}
			});
		}
//以下略

という感じですね。

ここまでで動かしてみると、[+][-][=]は動きませんが、
10進←→16進変換ツールとしては、まずまずのデキになります。

10進数状態では、[A]〜[F]のキーは押しても何もしないのですが
堂々と存在しているのが、ちょっと気になるかもしれません。
10進数状態では、キー(ボタン)の文字を薄くしてみましょう。

void hkeytop(){
	for (int k=0;k<20;++k){
		if (fn[k]>=10) {
			if (radix==16) btn[k].setForeground(Color.BLACK);
			else btn[k].setForeground(Color.LIGHT_GRAY);
		}
	}
}

というメソッドを作って、ItemListenerから呼ぶようにします。
ついでに、まだ未実装の[+][-][=]キーは、隠すようにしておきます。
ここまでの全ソースは次のようになります。これはひとつの例ですから
多少異なっていても望みどおりに動けばOKです。

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;


public class Dentaku2 {
	Frame f0;
	Label dsp;
	Font fbig,fmid;
	Button btn[]=new Button[20];
	Checkbox hx,dc;
	CheckboxGroup cbg;

	int result=0;
	int radix=10;
	final int KCLR=-1, KPLS=-2, KMNS=-3, KEQU=-4;

	String lb[]={
		"A","B","C","D",
		"7","8","9","E",
		"4","5","6","F",
		"1","2","3","CLR",
		"0"," "," "," "
	};
	int fn[]={
			10,11,12,13,
			 7, 8, 9,14,
			 4, 5, 6,15,
			 1, 2, 3,KCLR,
			 0,KPLS,KMNS,KEQU
		};

	Dentaku2(){
		f0=new Frame();
		f0.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent ev) {
                System.exit(0);
            }
        });
		f0.setTitle("decHEX2");
		fbig=new Font("Monospaced",Font.PLAIN,36);
		fmid=new Font("Monospaced",Font.PLAIN,24);

		dsp=new Label("0");
		dsp.setAlignment(Label.RIGHT);
		dsp.setFont(fbig);
		dsp.setBackground(Color.LIGHT_GRAY);

		Panel p1=new Panel();
		p1.setLayout(new BorderLayout());

		cbg=new CheckboxGroup();
		dc=new Checkbox("dec",true,cbg);
		hx=new Checkbox("HEX",false,cbg);
		Panel prd=new Panel();
		prd.setLayout(new FlowLayout(FlowLayout.LEFT));
		prd.add(dc); prd.add(hx);
		p1.add(prd,BorderLayout.SOUTH);
		p1.add(dsp,BorderLayout.CENTER);

		Panel keys=new Panel();
		keys.setLayout(new GridLayout(5,4));
		for (int i=0;i<20;++i) {
			if (fn[i]>=0) btn[i]=new nBtn(lb[i],fn[i]);
			else {
				btn[i]=new Button(lb[i]);
				if (fn[i]==KCLR) {
					btn[i].addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							result=0;display();
						}
					});
				}
/*
				switch (vn[i]) {
				case KCLR:
					btn[i].addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							result=0;display();
						}
					});
					break;
				default:
						break;
				}
*/
			}
			btn[i].setFont(fmid);
			keys.add(btn[i]);
		}
		hx.addItemListener(new setRadix());
		dc.addItemListener(new setRadix());

		hkeytop();
		f0.add(p1,BorderLayout.NORTH);
		f0.add(keys,BorderLayout.CENTER);
		f0.setSize(300,300);
		f0.setVisible(true);
	}
	public static void main(String[] args) {
		new Dentaku2();
	}
	void display(){
		String rs;
		if (radix==10)	rs=Integer.toString(result);
		else rs=Integer.toHexString(result).toUpperCase();
		dsp.setText(rs);
	}
	void hkeytop(){
		for (int k=0;k<20;++k){
			if (fn[k]>=10) {
				if (radix==16) btn[k].setForeground(Color.BLACK);
				else btn[k].setForeground(Color.LIGHT_GRAY);
			}
		}
	}
	class nBtn extends Button implements ActionListener {
		private static final long serialVersionUID = 1L;
		int nn;
		nBtn(String lb,int v){
			super(lb);
			nn=v;
			this.addActionListener(this);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			if ((radix==16)||(nn<10)) {
				result=result*radix+nn;
				display();
			}
		}
	}
	class setRadix implements ItemListener {
		@Override
		public void itemStateChanged(ItemEvent e) {
			if (hx.getState()) radix=16;
			else radix=10;
			hkeytop();
			display();
		}
	}
}

[CLR]キーの登録処理のあとに switch-case 文がコメント状態で
入っているのは、明日に向けての準備です。
明日は、[+][-][=]の演算処理を組み込んでみましょう。

ご意見、ご質問などがございましたらメールフォームからご連絡をお願いします。

16進電卓を作ってみよう1
16進電卓を作ってみよう2
16進電卓を作ってみよう3
16進電卓を作ってみよう4(this)
16進電卓を作ってみよう5
16進電卓を作ってみよう6
16進電卓を作ってみよう7
16進電卓を作ってみよう8
16進電卓を作ってみよう9

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

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

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

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