#犯行動機
JavaFXを始めるとだいたい電卓に行き着くじゃないですか
チュートリアル通り普通の電卓やっても面白くないし、
- むしゃくしゃしてやった
- 反省はしている
#イメージ
- ボタンを増やすと画面設計がそもそも大変
- 入力が漢数字はやりにくい
ということから、普通の電卓と基本は同じになるでしょう
そこで気付いた
漢数字って縦書きじゃね?
つまり、表示画面は縦書きにする必要がある
#画面レイアウト
つまりこういうことだな
これはひどい
素晴らしいデザインになりました
なお、labelに縦書き機能はないし、文字数が入りきらないから改行する機能を利用して、横幅1文字分にすることで縦書きにする
フォントを変えればよかったのでは
#作りましょう
犯行に至ります
ちなみに、普段がC#なので、クセでメソッド名が大文字から始まってます
見た目はこっちの方が好きなんだ ごめんねJava
##変数
四則演算用のモードとその変数を準備
計算に使う文字列と表示する時に使う文字列を用意
enum Calc{Plus,Minus,Multiplied,Dividid}
@FXML
Label label;
Calc calcMode = Calc.Plus; //四則演算モード管理変数
String calc = "",Output = ""; //計算用文字列と表示用文字列
ここら辺をこねくり回してしまえば計算できるでしょう
##メソッド
###ボタン
ボタンが押された時の処理をメソッドに集結させて楽します
@FXML void Num0(){ InputNum(0); }
@FXML void Num1(){ InputNum(1); }
@FXML void Num2(){ InputNum(2); }
@FXML void Num3(){ InputNum(3); }
@FXML void Num4(){ InputNum(4); }
@FXML void Num5(){ InputNum(5); }
@FXML void Num6(){ InputNum(6); }
@FXML void Num7(){ InputNum(7); }
@FXML void Num8(){ InputNum(8); }
@FXML void Num9(){ InputNum(9); }
@FXML void Plus(){calcMode = Calc.Plus; InputNum(); }
@FXML void Minus(){calcMode = Calc.Minus; InputNum(); }
@FXML void Multiplied(){calcMode = Calc.Multiplied; InputNum(); }
@FXML void Divided(){calcMode = Calc.Dividid; InputNum(); }
@FXML void Clear(){label.setText(calc = Output = "");}
@FXML
void Equal(){
String[] s = calc.split(" ");
int a = Integer.parseInt(s[0]);
int b = Integer.parseInt(s[1]);
int ans = 0;
switch(calcMode){
case Plus:
ans = a + b;break;
case Minus:
ans = a - b;break;
case Multiplied:
ans = a * b;break;
case Dividid:
ans = a / b;break;
}
System.out.println(a + "" + calcMode + b + " = " + ans);
//結果が0なら零、負なら「負 結果」になるように三項演算子
Output = Output + "\n⇓\n"
+ (ans != 0 ?
(ans > 0 ? Japaneser(ans):"負" + Japaneser(-ans))
: "零");
label.setText(Output);
}
Equalが押されたら演算モード次第で計算し表示、
数字と四則演算の処理は以下のメソッドへ
//数字を文字列にして渡す
void InputNum(int num){
InputNum(Integer.toString(num));
}
//四則演算は空白として文字列に追加
void InputNum(){
InputNum(" ");
}
//計算用文字列に引数を追加
void InputNum(String str){
calc = calc + str;
System.out.println("*デバッグ calc=>" + calc + ":");
Output();
}
###表示
空白がないと、四則演算を行わないので、計算用文字列を漢数字にそのまま変換します
//ラベル更新メソッド
void Output(){
if(!calc.contains(" ")){ //空白がなければそのまま
Output = Japaneser(calc);
}
else{
String[] calcStr = calc.split(" ");//空白で区切る
Output = Japaneser(calcStr[0])+ Calc() +
(calcStr.length > 1? Japaneser(calcStr[1]) : "");
}
label.setText(Output);
}
//四則演算文字メソッド
String Calc(){
switch(calcMode){
case Plus:return "\n足\n";
case Minus:return "\n引\n";
case Multiplied:return "\n掛\n";
case Dividid:return "\n割\n";
default :return null;
}
}
###漢数字にしよう
算用数字を漢数字に変換するには
10,100,1000,10000で区切りを付けて漢数字にする必要がある
となると、算用数字の桁数を知ればいけるかな
//数字を漢数字に翻訳
String Japaneser(int num){
String str = "";
int digit = (int)Math.pow(10,(num+"").length()-1);//文字数から桁数を出す
for(; num != 0; digit /= 10){
if(num >= digit){
int divid = num/digit;
str = str
+(num == 1 || divid != 1 ? ToJp(divid) : "")
+(digit != 1 ? ToJp(digit) : "");//0対策
num -= divid * digit; //上の桁から漢数字に変換していく
}
}
return str;
}
String Japaneser(String nums){
if(nums.length() > 4) return label.getText();
return Japaneser(Integer.parseInt(nums));
}
//数字を漢数字に変換
String ToJp(int num){
switch(num){
case 1:return "一";
case 2:return "二";
case 3:return "三";
case 4:return "四";
case 5:return "五";
case 6:return "六";
case 7:return "七";
case 8:return "八";
case 9:return "九";
case 10:return"十";
case 100:return"百";
case 1000:return"千";
default:
System.out.println("!!万の位には対応していません!!");
return null;
}
}
なお、万の位を超えると大変だったので、未対応です
そこに関して電卓としてのプライドは捨ててます
#仕様通りに使用しよう
そういえばintでやってるから小数ねぇ!!
まぁいっか!
#評価
制作中の画像を見せたところ、「結果」じゃなくて「↓」なのか
というお声をいただき、やってみたところ↓
こ れ は 読 め ね ぇ
- 「マイナスを負としてるのは面白い」
- 「レ点が入ってませんよ」
- 「白文だね」
- 「予想の斜め上だった」
などの微妙な反応素晴らしいお声をいただき、~~悪夢を続ける!~~続編を作成!
#画面レイアウト ver2
続編では漢数電卓がパワーアップして帰ってきた!!
漢数字にちなみ「和」の表現を増すために木目調の画像を使用し
配色も変更することで、より使いやすさを増しました
前作に比べ、
- 一般的な電卓の表示に変更(「一足二→三」のような式の表示を廃止)
- 負数にできる(なぜなかった)
- √(根)
- 小数(やっとか)
を実装しました
#プログラミングる
##変数
変数名は違いますが役割は前作と似たようなものです
private String op = null;
private double result = 0;
private double value = 0;
// 表示欄のラベル
@FXML private Label label;
String calc = "";
##メソッド
###数字ボタン
// 数字ボタンが押されたときの処理
@FXML private void numberPressed(ActionEvent event) {
Button bt = (Button) event.getSource();// 押されたボタンとその文字を取得する
String digit = ToMath(bt.getText()); //漢数字を算用数字に変換
calc = calc + digit;
label.setText(Japaneser(calc));
value = Double.parseDouble(calc);
}
###演算子ボタン
// 演算子ボタンが押されたときの共通処理
@FXML private void operatorPressed(ActionEvent event) {
Button bt = (Button) event.getSource();// 押されたボタンとその文字を取得する
String opname = bt.getText();
if (null == op) {
if(!opname.equals("根"))result = value;
else result = Math.sqrt(Double.parseDouble(calc));
} else {
switch (op) {
case "足":
result = result + value;
break;
case "引":
result = result - value;
break;
case "掛":
result = result * value;
break;
case "割":
result = result / value;
break;
case "根": //平方根を連打できるように
result = Math.sqrt(result);
break;
default:
break;
}
}
label.setText((result >= 0 ? //正負で処理を分ける
Japaneser(Double.toString(result)):
"負" + Japaneser(Double.toString(-result))));
calc = "";
if (opname.equals("結果")) {
op = null;
} else {
op = opname;
}
value = 0;
}
###小数ボタン
// 小数点ボタンが押された時の処理
@FXML private void pointPressed() {
String str = label.getText();
if(str.contains("・")){
String[] calcs = calc.split("\\.");
calc = calcs[0] + (calcs.length>1 ? calcs[1] : "");
str = Japaneser(calc);
}
else{
str = str + "・";
calc = calc + ".";
}
label.setText(str);
}
###クリアボタン
// C(クリア)ボタンが押された時の処理
@FXML private void clearPressed() {
op = null;
result = value = 0;
calc = "";
label.setText("");
}
###ルートボタン
@FXML void Root(){
double r = Math.sqrt( Double.parseDouble(calc));
result = r;
calc = Double.toString(r);
label.setText(Japaneser(calc));
}
###正負ボタン
@FXML void Minus(){
String str = label.getText();
if(str.contains("負")){
str = str.substring(1);
}
else{
str = "負" + str;
}
value *= -1;
calc = "-" + calc;
label.setText(str);
}
###漢数字変換
//数字を漢数字に翻訳
String Japaneser(int num){
String str = "";
int digit = (int)Math.pow(10,(num+"").length()-1);
for(; num != 0; digit /= 10){
if(num >= digit){
int divid = num/digit;
str = str
+(num == 1 || divid != 1 ? ToJp(divid) : "")//一残り対策
+(digit != 1 ? ToJp(digit) : "");//桁上がり0対策
num -= divid * digit; //上の桁から漢数字に変換していく
}
}
return str;
}
//文字列(数字)を漢数字に変換
String Japaneser(String str){
String[] strs = str.split("\\.");
String round = (strs[0].equals("0") ? //0だったら零
"零" :
Japaneser(Integer.parseInt( strs[0])));//整数部分を翻訳
if(strs.length > 1){
String[] chars = strs[1].split(""); //1文字づつに分解
if(chars.length > 1 || !chars[0].equals("0")){
round = round + "・";
for(String s : chars){
round = round + ToJp(Integer.parseInt(s));
}
}
}
return round;
}
//漢数字を数字に変換
String ToMath(String jp){
switch(jp){
case "桁増":
case "零":return "0";
case "一":return "1";
case "二":return "2";
case "三":return "3";
case "四":return "4";
case "五":return "5";
case "六":return "6";
case "七":return "7";
case "八":return "8";
case "九":return "9";
case "・":return ".";
case "負":return "-";
default: return "E";
}
}
//数字を漢数字に変換
String ToJp(int num){
switch(num){
case 0:return "零";
case 1:return "一";
case 2:return "二";
case 3:return "三";
case 4:return "四";
case 5:return "五";
case 6:return "六";
case 7:return "七";
case 8:return "八";
case 9:return "九";
case 10:return"十";
case 100:return"百";
case 1000:return"千";
case 10000:return"万";
default:
System.out.println("Error");
return null;
}
}
#使ってみよう
前作と違い、一般的な電卓と同じく連続で計算できます
1+2+3 / 5 * 6
みたいな
##引き算
65-96=-31
##割り算
1096/3=365.3333333333333
##ルート
√5 = 2.23606797749979
#まとめ
いかがだったでしょうか 万の桁にも対応できてませんが
このデザイン性と使い勝手はその方面からは「これは凄い」と評価頂けるのではないでしょうか
- 入力は算用数字なのに表示は漢数字
- そもそも使いにくい
- 見にくい
など、様々な感想を 持ったので お持ちと思いますので、お読みの皆様も漢数電卓をデザインしてみると面白いと思います
#漢数電卓という選択肢
以上のように漢数電卓には様々な可能性を秘めています
そのため、今後 電卓を使う際の選択肢に漢数電卓は、**なし
**です
当たり前ですね