(IntelliJ IDEA)基于JavaFX的简易四则运算器开发2.0(修复了一些bug,分成了两个文件方便维护)

bug修复:

1. 括号隔开两数输出后为一个数,例如:4()5=5,或者一个数后跟括号,括号内为数字或表达式,输出为括号内值,例如:4(5-7)=-2。

2. 除数为零时文本框缺少输出。(其实这个应该不算bug,只是没写显示的内容,导致文本框内容不变,我记得是这样的,控制台那边是有显示的,异常处理是写了的)。

优化:

1.JavaFX的按钮创建改成了用二维数组循环创建,其实这应该不算是优化,毕竟复杂一点性能就会差,好在计算器比较简单,用二维数组创建还更为直观,我觉得。

2. 去除了不需要的一些代码,本来写了两个addButtonToGrid方法,第二个多一个参数方便直接指定按钮的列跨度,免得第一个多次调用,结果发现其实用不到。

3. 使用常量替换字符串,虽然最后只改了报错的地方的字符串,主要其他字符串都比较短,个人美观上不接受换为常量。

4. 将界面和逻辑分离,写在两个不同的Java文件中——放Calculator 类的文件和放CalculatorLogic 类的文件。

        Calculator文件包含主应用程序和界面的创建逻辑。

        CalculatorLogic文件包含计算器的逻辑和按钮事件处理的方法。

哦对了,因为之前注释太长,看之前代码好麻烦,(虽然其实可以折叠代码,但是我真的很懒,点开、折叠好麻烦),我把注释都删了好像,懒得写了,其实大体上没变什么,可以参照上一个读。

Calculator.java 代码如下:

package com.example.hellofx;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import static com.example.hellofx.CalculatorLogic.ERROR_EXPRESSION;
import static com.example.hellofx.CalculatorLogic.evaluateExpression;

public class Calculator extends Application {
    public static TextField inputField;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("简易四则计算器");
        GridPane gridPane = createGridPane();
        Scene scene = new Scene(gridPane, 320, 502);
        primaryStage.setScene(scene);
        inputField = createInputField();

        gridPane.add(inputField, 0, 0, 4, 1);
        addButtonsToGrid(gridPane);

        primaryStage.show();
    }

    private GridPane createGridPane() {
        GridPane gridPane = new GridPane();
        gridPane.setHgap(6);
        gridPane.setVgap(9);
        gridPane.setPadding(new Insets(10));
        return gridPane;
    }

    private TextField createInputField() {
        TextField textField = new TextField();
        textField.setStyle("-fx-alignment: bottom-left;");
        textField.setStyle("-fx-padding: 0 0 -30 0;");
        textField.setEditable(false);
        textField.setPrefHeight(125);
        textField.setFont(Font.font(21));
        return textField;
    }

    private void addButtonToGrid(GridPane gridPane, String text, int col, int row) {
        Button button = new Button(text);
        button.setOnAction(e -> handleButtonAction(text));
        button.setPrefSize(70, 50);
        button.setFont(Font.font(16));
        gridPane.add(button, col, row);
    }

    private void addButtonsToGrid(GridPane gridPane) {
        String[][] buttonLabels = {
                {"AC", "DEL", "(", ")"},
                {"7", "8", "9", "/"},
                {"4", "5", "6", "*"},
                {"1", "2", "3", "-"},
                {".", "0", "00", "+"},
                {"", "", "", "="}
        };
        for (int row = 1; row < buttonLabels.length + 1; row++) {
            for (int col = 0; col < buttonLabels[row - 1].length; col++) {
                String label = buttonLabels[row - 1][col];
                if (!label.isEmpty())
                    addButtonToGrid(gridPane, label, col, row);
            }
        }
    }

    private void handleButtonAction(String text) {
        switch (text) {
            case "=" -> {
                String expression = inputField.getText();
                if (isParenthesesMatched(expression)) {
                    if (containsArithmeticOperator(expression)) {
                        double result = evaluateExpression(expression);
                        if (result % 1 == 0) {
                            int intResult = (int) result;
                            inputField.setText(String.valueOf(intResult));
                        } else
                            inputField.setText(String.valueOf(result));
                    } else
                        inputField.setText(ERROR_EXPRESSION);
                } else
                    inputField.setText(ERROR_EXPRESSION);
            }
            case "AC" -> inputField.clear();
            case "DEL" -> {
                String currentText = inputField.getText();
                if (!currentText.isEmpty())
                    inputField.setText(currentText.substring(0, currentText.length() - 1));
            }
            default -> inputField.appendText(text);
        }
    }

    private boolean containsArithmeticOperator(String expression) {
        return expression.matches(".*[+\\-*/].*");
    }

    private boolean isParenthesesMatched(String expression) {
        int count = 0;
        for (char ch : expression.toCharArray()) {
            if (ch == '(')
                count++;
            else if (ch == ')')
                count--;
            if (count < 0)
                return false;
        }
        return count == 0;
    }
}

CalculatorLogic.java 代码如下:

package com.example.hellofx;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import static com.example.hellofx.Calculator.inputField;

public final class CalculatorLogic {
    static final String ERROR_EXPRESSION = "非法输入";
    static final String ERROR_BY_ZERO = "除数不可为零";

    private CalculatorLogic() {
    }

    public static double evaluateExpression(String expression) {
        expression = expression.replaceAll("\\s+", "");
        Stack<Character> operatorStack = new Stack<>();
        Stack<Double> operandStack = new Stack<>();
        Map<Character, Integer> precedence = new HashMap<>();
        precedence.put('+', 1);
        precedence.put('-', 1);
        precedence.put('*', 2);
        precedence.put('/', 2);

        int i = 0;
        while (i < expression.length()) {
            char ch = expression.charAt(i);
            if (Character.isDigit(ch) || ch == '.') {
                StringBuilder sb = new StringBuilder();
                i = getI(expression, operandStack, i, sb);
            } else if (ch == '(') {
                operatorStack.push(ch);
                i++;
            } else if (ch == ')') {
                while (!operatorStack.isEmpty() && operatorStack.peek() != '(')
                    applyOperator(operatorStack.pop(), operandStack, operatorStack);
                operatorStack.pop();
                i++;
            } else if (isOperator(ch)) {
                if (ch == '-' && (i == 0 || expression.charAt(i - 1) == '(')) {
                    i++;
                    StringBuilder sb = new StringBuilder("-");
                    i = getI(expression, operandStack, i, sb);
                } else {
                    while (!operatorStack.isEmpty() && operatorStack.peek() != '(' && precedence.get(ch) <= precedence.get(operatorStack.peek()))
                        applyOperator(operatorStack.pop(), operandStack, operatorStack);
                    operatorStack.push(ch);
                    i++;
                }
            } else
                i++;
        }
        while (!operatorStack.isEmpty())
            applyOperator(operatorStack.pop(), operandStack, operatorStack);
        if (!operandStack.isEmpty())
            return operandStack.pop();
        else
            throw new IllegalArgumentException(ERROR_EXPRESSION);
    }

    private static int getI(String expression, Stack<Double> operandStack, int i, StringBuilder sb) {
        while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
            sb.append(expression.charAt(i));
            i++;
        }
        double operand = Double.parseDouble(sb.toString());
        operandStack.push(operand);
        return i;
    }

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


    private static void applyOperator(char operator, Stack<Double> operandStack, Stack<Character> operatorStack) {
        if (operandStack.size() < 2) {
            inputField.setText(ERROR_EXPRESSION);
            throw new IllegalArgumentException(ERROR_EXPRESSION);
        }
        double operand2 = operandStack.pop();
        double operand1 = operandStack.pop();
        double result = switch (operator) {
            case '+' -> operand1 + operand2;
            case '-' -> operand1 - operand2;
            case '*' -> operand1 * operand2;
            case '/' -> {
                if (operand2 == 0) {
                    inputField.setText(ERROR_BY_ZERO);
                    throw new ArithmeticException(ERROR_BY_ZERO);
                }
                yield operand1 / operand2;
            }
            default -> 0;
        };
        operandStack.push(result);
        if (!operandStack.isEmpty() && operandStack.peek() < 0) {
            if (!operatorStack.isEmpty()) {
                char nextOperator = operatorStack.peek();
                if (nextOperator == '+' || nextOperator == '-') {
                    double negativeResult = operandStack.pop();
                    operandStack.push(-negativeResult);
                }
            }
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值