16進電卓を作ってみよう7
プログラムは、最初のうちは単純な形であっても
機能追加やバグ対処などをおこなうと次第に複雑になってゆくものです。
毎度、管理人イガジーです。
プログラムが複雑になる理由は色々ありますが、何かを決定するための
条件が多くなるためというケースが多いと思います。
さて、16進電卓の続きです。
前回の困った動作を解決するために、
[1][+][2][=] と操作して(結果として「3」が表示されている状態で)
(aa)数字キー([0]〜[9])が押されたら、結果(result)をクリアして、
入力された数字をresultに格納する。
(bb)演算キー([+]や[-])や、HEX/decの切り替えが行われた場合は
結果(result)を保持したままとする。
という処理を追加しましょう。
[=]キーの処理で、resultを0にすると、(bb)が満たせなくなるので、
ここでは「次に押されるキーが数字だったらresultを0にする」
準備だけを行います。
case KEQU:
btn[i].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (stat==ADD) {
result=val1+result;
}else if (stat==SUB) {
result=val1-result;
}
stat=NEXT; // [=]が押された状態だという事を覚えておく
display();
}
});
break;
実際にresultを0にするのは、数字キー([0]〜[9])の処理になります。
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)) {
if (stat==NEXT) { // [=]が押されたあとであれば
result=0; // クリアする
stat=NOP;
}
result=result*radix+nn;
display();
}
}
}
次に連続演算([1][+][2][+][3][=] など)も頑張ってみましょう。
[+][-]の処理でも、そこまでの演算をしてしまえば良いのです。
[=]でも[+]でも[-]でも演算をするので、共通のメソッドにします。
int calc(){
int rv=result;
if (stat==ADD) {
rv=val1+result;
}else if (stat==SUB) {
rv=val1-result;
}
return rv;
}
そして、[+]キーの処理では
public void actionPerformed(ActionEvent e) {
val1=calc();
stat=ADD;
result=0;
display("+");
}
と演算してから[+]が押された事を覚えるようにします。
[-]キーの処理も、ほぼ同じです。
ここまでのプログラム例を掲載しておきます。
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 Dentaku4 {
Frame f0;
Label dsp;
Font fbig,fmid;
Button btn[]=new Button[20];
Checkbox hx,dc;
CheckboxGroup cbg;
final int NOP=0, ADD=1, SUB=2, NEXT=3;
int result=0,val1=0;
int radix=10;
int stat=NOP;
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
};
Dentaku4(){
f0=new Frame();
f0.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent ev) {
System.exit(0);
}
});
f0.setTitle("decHEX4");
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]);
switch (fn[i]) {
case KCLR:
btn[i].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
result=val1=0;
display();
}
});
break;
case KPLS:
btn[i].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
val1=calc();
stat=ADD;
result=0;
display("+");
}
});
break;
case KMNS:
btn[i].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
val1=calc();
stat=SUB;
result=0;
display("-");
}
});
break;
case KEQU:
btn[i].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
result=calc();
stat=NEXT;
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 Dentaku4();
}
void display(){
String rs;
if (radix==10) rs=Integer.toString(result);
else rs=Integer.toHexString(result).toUpperCase();
dsp.setText(rs);
}
void display(String s){
dsp.setText(s);
}
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);
}
}
}
int calc(){
int rv=result;
if (stat==ADD) {
rv=val1+result;
}else if (stat==SUB) {
rv=val1-result;
}
return rv;
}
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)) {
if (stat==NEXT) {
result=0;
stat=NOP;
}
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();
}
}
}
これで完成としましょうか。
でも、ちょっと意地悪して、数字をどんどん入力して桁を増やすと
ある時点でマイナス値になってしまいます。
例えば、12345678901 と入力すると
−539222987 になってしまいます。
これは、result などの変数に格納する際のオーバフローです。
自分用なら無視しても良いのですが、どうしましょう?
ちょっと考えてみてください。
16進電卓を作ってみよう1
16進電卓を作ってみよう2
16進電卓を作ってみよう3
16進電卓を作ってみよう4
16進電卓を作ってみよう5
16進電卓を作ってみよう6
16進電卓を作ってみよう7(this)
16進電卓を作ってみよう8
16進電卓を作ってみよう9
この記事へのコメントはこちら