JavaFXとJavaScriptを使った簡易電卓

JavaFXでFXMLと呼ばれるXMLファイルにJavaScriptを記述することができます。JavaScriptのeval()関数という式を評価する関数を使って、簡易電卓を作成しました。

#画面

以下の画面です。

![calc.png](https://qiita-image-store.s3.amazonaws.com/0/133921/891d8266-3b00-8367-d28b-13e2818c2c28.png)


#使用したソフト
開発には以下のソフトを使いました。

+ Eclipse + e(fx)clipse - IDEプラグイン
+ JavaFX Scene Builder 8.2.0

#手順
JavaFX Library Projectを作成します。srcフォルダにapplicationパッケージを作成し、その直下にMain.javaとapp.fxmlを作成します。

Main.javaは以下の内容にします。

```Java:Main.java
package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;


public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
        BorderPane root;
		try {
            root = (BorderPane)FXMLLoader.load(getClass().getResource("app.fxml"));
            Scene scene = new Scene(root,250,320);
			primaryStage.setScene(scene);
			primaryStage.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}
```
app.fxmlですが、手順としては以下になります。

* JavaFX Scene Builderでラベル、テキストフィールド、ボタンを配置。
* テキストエディタで以下を記述します。
    * 「<?language javascript?>」を追加。
    * onActionを記述（JavaFX Scene Builder上でもできます。）
    * &lt;fx:script&gt;～&lt;/fx:script&gt;を記述

細かい部分は以下にfxmlの内容を貼り付けますので、そちらで。そのままコピーして貼り付けて使えると思います。

```xml:app.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?language javascript?>

<BorderPane xmlns="http://javafx.com/javafx/" xmlns:fx="http://javafx.com/fxml/1">
    <fx:script>
    function insert(symbol) {
    	var text = textFieldFormula.text;
    	text += symbol;
        textFieldFormula.text = text;
    }

    function calc() {
    	var formulaText = textFieldFormula.text;

		// 空チェック
		if (formulaText === "") {
			textFieldValue.text = "未入力です。";
			return ;
		}

    	// 想定外の文字が入力されているかチェック
    	if (formulaText.search(/^[%()*+-/0-9]+$/)) {
			textFieldValue.text = "余計な文字があります。";
			return ;
    	}

    	var value = "";
    	try {
    		value = eval(formulaText);
    	} catch(e) {
    		value = "結果がありませんでした。";
    	}
		textFieldValue.text = value;

    }

    function clear() {
	    	textFieldFormula.text = "";
	    	textFieldValue.text = "";
    }
    </fx:script>
   <center>
      <Pane prefHeight="334.0" prefWidth="255.0" BorderPane.alignment="CENTER">
         <children>
            <TextField fx:id="textFieldFormula" layoutX="29.0" layoutY="12.0" prefHeight="25.0" prefWidth="202.0" promptText="式を入力してください。" />
            <TextField fx:id="textFieldValue" editable="false" layoutX="29.0" layoutY="52.0" prefHeight="25.0" prefWidth="202.0" promptText="=ボタンを押すと計算結果が出ます。" />
            <Label layoutX="14.0" layoutY="16.0" text="式" />
            <Label layoutX="14.0" layoutY="56.0" text="値" />
            <Button layoutX="14.0" layoutY="174.0" mnemonicParsing="false" onAction="insert('1');" prefHeight="30.0" prefWidth="30.0" text="1" />
            <Button layoutX="52.0" layoutY="174.0" mnemonicParsing="false" onAction="insert('2');" prefHeight="30.0" prefWidth="30.0" text="2" />
            <Button layoutX="88.0" layoutY="174.0" mnemonicParsing="false" onAction="insert('3');" prefHeight="30.0" prefWidth="30.0" text="3" />
            <Button layoutX="14.0" layoutY="132.0" mnemonicParsing="false" onAction="insert('4');" prefHeight="30.0" prefWidth="30.0" text="4" />
            <Button layoutX="52.0" layoutY="132.0" mnemonicParsing="false" onAction="insert('5');" prefHeight="30.0" prefWidth="30.0" text="5" />
            <Button layoutX="88.0" layoutY="132.0" mnemonicParsing="false" onAction="insert('6');" prefHeight="30.0" prefWidth="30.0" text="6" />
            <Button layoutX="14.0" layoutY="90.0" mnemonicParsing="false" onAction="insert('7');" prefHeight="30.0" prefWidth="30.0" text="7" />
            <Button layoutX="52.0" layoutY="90.0" mnemonicParsing="false" onAction="insert('8');" prefHeight="30.0" prefWidth="30.0" text="8" />
            <Button layoutX="88.0" layoutY="90.0" mnemonicParsing="false" onAction="insert('9');" prefHeight="30.0" prefWidth="30.0" text="9" />
            <Button layoutX="14.0" layoutY="214.0" mnemonicParsing="false" onAction="insert('0');" prefHeight="30.0" prefWidth="30.0" text="0" />
            <Button layoutX="128.0" layoutY="90.0" mnemonicParsing="false" onAction="insert('+');" prefHeight="30.0" prefWidth="30.0" text="+" />
            <Button layoutX="128.0" layoutY="132.0" mnemonicParsing="false" onAction="insert('-');" prefHeight="30.0" prefWidth="30.0" text="-" />
            <Button layoutX="163.0" layoutY="90.0" mnemonicParsing="false" onAction="insert('*');" prefHeight="30.0" prefWidth="30.0" text="*" />
            <Button layoutX="163.0" layoutY="132.0" mnemonicParsing="false" onAction="insert('/');" prefHeight="30.0" prefWidth="30.0" text="/" />
            <Button layoutX="163.0" layoutY="174.0" mnemonicParsing="false" onAction="insert('\%');" prefHeight="30.0" prefWidth="30.0" text="\%" />
            <Button layoutX="200.0" layoutY="90.0" mnemonicParsing="false" onAction="insert('(');" prefHeight="30.0" prefWidth="30.0" text="(" />
            <Button layoutX="200.0" layoutY="132.0" mnemonicParsing="false" onAction="insert(')');" prefHeight="30.0" prefWidth="30.0" text=")" />
            <Button layoutX="128.0" layoutY="214.0" mnemonicParsing="false" onAction="calc();" prefHeight="30.0" prefWidth="30.0" text="=" />
            <Button layoutX="163.0" layoutY="214.0" mnemonicParsing="false" onAction="clear();" prefHeight="30.0" prefWidth="30.0" text="C" />
         </children>
      </Pane>
   </center>
</BorderPane>
```

以上の2ファイルを用意すれば、Main.javaを右クリック->実行->Javaアプリケーションをクリックして起動できます。

#修正履歴

##20160806
pyominさんの指摘に対応しました。

* calc()メソッドに入力チェックを追加。