JavaFX实现计算器

今年疫情导致开学晚,在家自学javafx过程中想活学活用故此准备编写一个计算器。先将结果进行展示,然后进行代码的分析。下面看看源代码:


package ff;
import java.util.Collections;
import java.util.Stack;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.text.Font;

public class 计算器 extends Application {
    StringBuilder lab = new StringBuilder();
    Label label1 = new Label();
    double q, h, s;
    String op;

    @Override
    public void start(Stage primaryStage) {
//        String[] button=new String[24];
//        for(int i=0;i<24;i++){
////            Button button[i]=new Button();
////        }

        GridPane pane1 = new GridPane();
        pane1.setAlignment(Pos.CENTER);
        //添加节点
        Button button0 = new Button("mc");
        button0.setPrefSize(200, 100);button0.setFont(Font.font(50));
        Button button2 = new Button("(");
        button2.setPrefSize(200, 100);button2.setFont(Font.font(50));
        Button button3 = new Button(")");
        button3.setPrefSize(200, 100);button3.setFont(Font.font(50));
        Button button1 = new Button("mr");
        button1.setPrefSize(200, 100);button1.setFont(Font.font(50));

        Button button4 = new Button("C");
        button4.setPrefSize(200, 100);button4.setFont(Font.font(50));
        Button button5 = new Button("/");
        button5.setPrefSize(200, 100);button5.setFont(Font.font(50));
        Button button6 = new Button("*");
        button6.setPrefSize(200, 100);button6.setFont(Font.font(50));
        Button button7 = new Button("D");
        button7.setPrefSize(200, 100);button7.setFont(Font.font(50));

        Button button8 = new Button("7");
        button8.setPrefSize(200, 100);button8.setFont(Font.font(50));
        Button button9 = new Button("8");
        button9.setPrefSize(200, 100);button9.setFont(Font.font(50));
        Button button11 = new Button("9");
        button11.setPrefSize(200, 100);button11.setFont(Font.font(50));
        Button button12 = new Button("-");
        button12.setPrefSize(200, 100);button12.setFont(Font.font(50));

        Button button13 = new Button("4");
        button13.setPrefSize(200, 100);button13.setFont(Font.font(50));
        Button button14 = new Button("5");
        button14.setPrefSize(200, 100);button14.setFont(Font.font(50));
        Button button15 = new Button("6");
        button15.setPrefSize(200, 100);button15.setFont(Font.font(50));
        Button button16 = new Button("+");
        button16.setPrefSize(200, 100);button16.setFont(Font.font(50));

        Button button17 = new Button("1");
        button17.setPrefSize(200, 100);button17.setFont(Font.font(50));
        Button button18 = new Button("2");
        button18.setPrefSize(200, 100);button18.setFont(Font.font(50));
        Button button19 = new Button("3");
        button19.setPrefSize(200, 100);button19.setFont(Font.font(50));
        Button button21 = new Button("^");
        button21.setPrefSize(200, 100);button21.setFont(Font.font(50));

        Button button22 = new Button("%");
        button22.setPrefSize(200, 100);button22.setFont(Font.font(50));
        Button button23 = new Button("0");
        button23.setPrefSize(200, 100);button23.setFont(Font.font(50));
        Button button24 = new Button(".");
        button24.setPrefSize(200, 100);button24.setFont(Font.font(50));
        Button button25 = new Button("=");
        button25.setPrefSize(200, 100);button25.setFont(Font.font(50));

        pane1.add(button0, 0, 0);
        pane1.add(button1, 1, 0);
        pane1.add(button2, 2, 0);
        pane1.add(button3, 3, 0);

        pane1.add(button4, 0, 1);
        pane1.add(button5, 1, 1);
        pane1.add(button6, 2, 1);
        pane1.add(button7, 3, 1);

        pane1.add(button8, 0, 2);
        pane1.add(button9, 1, 2);
        pane1.add(button11, 2, 2);
        pane1.add(button12, 3, 2);

        pane1.add(button13, 0, 3);
        pane1.add(button14, 1, 3);
        pane1.add(button15, 2, 3);
        pane1.add(button16, 3, 3);

        pane1.add(button17, 0, 4);
        pane1.add(button18, 1, 4);
        pane1.add(button19, 2, 4);
        pane1.add(button21, 3, 4);

        pane1.add(button22, 0, 5);
        pane1.add(button23, 1, 5);
        pane1.add(button24, 2, 5);
        pane1.add(button25, 3, 5);
//        button0.setOnAction(event -> label1.setText("/"+""));
//        button1.setOnAction(event -> label1.setText("/"+""));
//        button2.setOnAction(event -> label1.setText("/"+""));
//        button3.setOnAction(event -> label1.setText("/"+""));

//        //button4.setOnAction(event -> label1.setText("/"+""));clear操作
//        button5.setOnAction(event -> label1.setText(label1.getText()+"/"));
//        button6.setOnAction(event -> label1.setText(label1.getText()+"*"));
//        //button7.setOnAction(event -> label1.setText("/"+""));//delete操作
//
//        button8.setOnAction(event -> label1.setText(label1.getText()+"7"));
//        button9.setOnAction(event -> label1.setText(label1.getText()+"8"));
//        button11.setOnAction(event -> label1.setText(label1.getText()+"9"));
//        button12.setOnAction(event -> label1.setText(label1.getText()+"-"));
//
//        button13.setOnAction(event -> label1.setText(label1.getText()+"4"));
//        button14.setOnAction(event -> label1.setText(label1.getText()+"5"));
//        button15.setOnAction(event -> label1.setText(label1.getText()+"6"));
//        button16.setOnAction(event -> label1.setText(label1.getText()+"+"));
//
//        button17.setOnAction(event -> label1.setText(label1.getText()+"1"));
//        button18.setOnAction(event -> label1.setText(label1.getText()+"2"));
//        button19.setOnAction(event -> label1.setText(label1.getText()+"3"));
//        button21.setOnAction(event -> label1.setText(label1.getText()+"^"));
//
//        button22.setOnAction(event -> label1.setText(label1.getText()+"%"));
//        button23.setOnAction(event -> label1.setText(label1.getText()+"0"));
//        button24.setOnAction(event -> label1.setText(label1.getText()+"."));
//        button25.setOnAction(event -> label1.setText(label1.getText()+"=
        button0.setOnAction(new action());
        button1.setOnAction(new action());
        button2.setOnAction(new action());
        button3.setOnAction(new action());

        button4.setOnAction(new action());//clear操作
        button5.setOnAction(new action());
        button6.setOnAction(new action());
        button7.setOnAction(new action());//delete操作

        button8.setOnAction(new action());
        button9.setOnAction(new action());
        button11.setOnAction(new action());
        button12.setOnAction(new action());

        button13.setOnAction(new action());
        button14.setOnAction(new action());
        button15.setOnAction(new action());
        button16.setOnAction(new action());

        button17.setOnAction(new action());
        button18.setOnAction(new action());
        button19.setOnAction(new action());
        button21.setOnAction(new action());

        button22.setOnAction(new action());
        button23.setOnAction(new action());
        button24.setOnAction(new action());
        button25.setOnAction(new action());

        label1.setPrefSize(800, 400);
        label1.setFont(Font.font(50));
        label1.setTextAlignment(TextAlignment.LEFT);
        //VBox pane2=new VBox(label1);
        //pane2.setAlignment(Pos.BASELINE_LEFT);

        VBox pane = new VBox(10, label1, pane1);

        Scene scene = new Scene(pane);
        primaryStage.setTitle("计算器");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    class action implements EventHandler<ActionEvent> {
        @Override
        public void handle(ActionEvent event) {
            String a = event.toString();
            String e = a.substring(a.length() - 3, a.length() - 2);
            char c = a.charAt(a.length() - 3);
            //System.out.println(c);

            if (e.equals("0") || e.equals("1") || e.equals("2") || e.equals("3")
                    || e.equals("4") || e.equals("5") || e.equals("6") || e.equals("7")
                    || e.equals("8") || e.equals("9") || e.equals(".")|| e.equals("+")
                    || e.equals("-") || e.equals("*") || e.equals("/")|| e.equals("^")|| e.equals("(")|| e.equals(")")
            ) {
                lab.append(e);//将字符进行记录
                label1.setText(lab.toString());
                System.out.println(e);
            } else if (e.equals("D")) {
                lab.deleteCharAt(lab.length() - 1);
                label1.setText(lab.toString());
                System.out.println("D");
            } else if (e.equals("C")) {
                lab = new StringBuilder();
                label1.setText(lab.toString());
            } else if (e.equals("=")){

                String expression = lab.toString();
                double result = zz.Calculator1.conversion(expression);
                System.out.println(expression + " = " + result);
                label1.setText(expression+"="+result);
            }
        }
    }
}
class ArithHelper {
    // 默认除法运算精度
    private static final int DEF_DIV_SCALE = 16;

    // 这个类不能实例化
    private ArithHelper() {
    }

    public static double add(double v1, double v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
        java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    public static double add(String v1, String v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
        java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
        return b1.add(b2).doubleValue();
    }

    public static double sub(double v1, double v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
        java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    public static double sub(String v1, String v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
        java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
        return b1.subtract(b2).doubleValue();
    }

    public static double mul(double v1, double v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
        java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    public static double mul(String v1, String v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
        java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
        return b1.multiply(b2).doubleValue();
    }

    public static double div(double v1, double v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    public static double div(String v1, String v2) {
        java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
        java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
        return b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
        java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        java.math.BigDecimal b = new java.math.BigDecimal(Double.toString(v));
        java.math.BigDecimal one = new java.math.BigDecimal("1");
        return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static double round(String v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        java.math.BigDecimal b = new java.math.BigDecimal(v);
        java.math.BigDecimal one = new java.math.BigDecimal("1");
        return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}

class Calculator1 {
    private Stack<String> postfixStack = new Stack<String>();
    private Stack<Character> opStack = new Stack<Character>();
    private int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 };// 运用运算符ASCII码-40做索引的运算符优先级

    public static double conversion(String expression) {
        double result = 0;
        zz.Calculator1 cal = new zz.Calculator1();
        try {
            expression = transform(expression);
            result = cal.calculate(expression);
        } catch (Exception e) {
            // e.printStackTrace();
            // 运算错误返回NaN
            return 0.0 / 0.0;
        }
        // return new String().valueOf(result);
        return result;
    }

    private static String transform(String expression) {
        char[] arr = expression.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == '-') {
                if (i == 0) {
                    arr[i] = '~';
                } else {
                    char c = arr[i - 1];
                    if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == 'E' || c == 'e') {
                        arr[i] = '~';
                    }
                }
            }
        }
        if(arr[0]=='~'||arr[1]=='('){
            arr[0]='-';
            return "0"+new String(arr);
        }else{
            return new String(arr);
        }
    }

    public double calculate(String expression) {
        Stack<String> resultStack = new Stack<String>();
        prepare(expression);
        Collections.reverse(postfixStack);// 将后缀式栈反转
        String firstValue, secondValue, currentValue;// 参与计算的第一个值,第二个值和算术运算符
        while (!postfixStack.isEmpty()) {
            currentValue = postfixStack.pop();
            if (!isOperator(currentValue.charAt(0))) {// 如果不是运算符则存入操作数栈中
                currentValue = currentValue.replace("~", "-");
                resultStack.push(currentValue);
            } else {// 如果是运算符则从操作数栈中取两个值和该数值一起参与运算
                secondValue = resultStack.pop();
                firstValue = resultStack.pop();

                // 将负数标记符改为负号
                firstValue = firstValue.replace("~", "-");
                secondValue = secondValue.replace("~", "-");

                String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));
                resultStack.push(tempResult);
            }
        }
        return Double.valueOf(resultStack.pop());
    }

    private void prepare(String expression) {
        opStack.push(',');// 运算符放入栈底元素逗号,此符号优先级最低
        char[] arr = expression.toCharArray();
        int currentIndex = 0;// 当前字符的位置
        int count = 0;// 上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
        char currentOp, peekOp;// 当前操作符和栈顶操作符
        for (int i = 0; i < arr.length; i++) {
            currentOp = arr[i];
            if (isOperator(currentOp)) {// 如果当前字符是运算符
                if (count > 0) {
                    postfixStack.push(new String(arr, currentIndex, count));// 取两个运算符之间的数字
                }
                peekOp = opStack.peek();
                if (currentOp == ')') {// 遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
                    while (opStack.peek() != '(') {
                        postfixStack.push(String.valueOf(opStack.pop()));
                    }
                    opStack.pop();
                } else {
                    while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) {
                        postfixStack.push(String.valueOf(opStack.pop()));
                        peekOp = opStack.peek();
                    }
                    opStack.push(currentOp);
                }
                count = 0;
                currentIndex = i + 1;
            } else {
                count++;
            }
        }
        if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {// 最后一个字符不是括号或者其他运算符的则加入后缀式栈中
            postfixStack.push(new String(arr, currentIndex, count));
        }

        while (opStack.peek() != ',') {
            postfixStack.push(String.valueOf(opStack.pop()));// 将操作符栈中的剩余的元素添加到后缀式栈中
        }
    }

    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
    }

    public boolean compare(char cur, char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低
        boolean result = false;
        if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) {
            result = true;
        }
        return result;
    }

    private String calculate(String firstValue, String secondValue, char currentOp) {
        String result = "";
        switch (currentOp) {
            case '+':
                result = String.valueOf(zz.ArithHelper.add(firstValue, secondValue));
                break;
            case '-':
                result = String.valueOf(zz.ArithHelper.sub(firstValue, secondValue));
                break;
            case '*':
                result = String.valueOf(zz.ArithHelper.mul(firstValue, secondValue));
                break;
            case '/':
                result = String.valueOf(ArithHelper.div(firstValue, secondValue));
                break;
        }
        return result;
    }
}

``

运行截图如图:JavaFX实现计算器
下面是进行运算的一个例子:
JavaFX实现计算器

在编写这个简单计算器的过程中,主要分成几个部分。首先是进行界面排版。然后就是对按钮事件的处理。当点击某个数字时需要获取该按钮的信息,并将信息显示到输入栏中。运算完成后将结果输出。

上一篇:Python笔记_第四篇_高级应用_GUI编程之Tkinter_5.鼠标事件


下一篇:DSAPI QQ用户相关