Foreword
It was my first time to write in Java. I learned a lot of things while writing, so I wrote a lot of notes (not many actually, mainly because I had to post CSDN and so on, so I added some later). I have never written such a program before, so I guess there are irregularities and bugs.
Although I am still a Java novice, IntelliJ is so easy to use. Not to mention smart completion, it can even help you optimize your code. Really, I cried to death! ! !
Shocked by teacher’s development speed haha
Background
Write a calculator class that supports cascade calls and can complete four simple arithmetic operations. Call example:
var result=new Calc(100).add(10).subtract(5).multiply(10).getResult();
What is done above is the calculation of 100 + 10-5*10, regardless of priority, and is purely calculated sequentially from left to right.
Require:
(1) The calculator class must be a read-only type
(2) The length of the cascade calling method chain is not limited
(3) Finally, provide a “terminal method” to end the entire call and give the calculation results.
I just learned the basics of JavaFX and used it. Everything else is fine. The calculation part of the code is actually very similar to a question in the National Day homework on data structure. It just changes the C language implementation into Java implementation. Using Java is a little simpler. The main problem is that I write too quickly and write all the functions without considering all the functions, which makes it time-consuming to change the code later (poor memory, I forget which part is the function of which part). The main reason is that I didn’t comment much when I first wrote it. The method is commented out).
The calculator class is required to be read-only, but I don’t know much about this (I happened to not be attending the class at the time – I was studying other people’s software), so I’ll look at it later.
var result=new Calc(100).add(10).subtract(5).multiply(10).getResult(); This requirement is also confusing, but I think if I write it this way, I can achieve continuous calculation and calling methods. There is a limit, but, if the characters exceed the text box, they will be invisible. I should write a method to automatically adjust the font size in the text box. It is too late today and I don’t want to write. I will swim at eight tomorrow morning and go to bed! ! !
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 java.util.HashMap; import java.util.Map; import java.util.Stack; public class Calculator extends Application { private TextField inputField; @Override public void start(Stage primaryStage) { //Set the title of the main stage primaryStage.setTitle("Calculator"); // Create grid layout container GridPane gridPane = createGridPane(); //Create a scene, use the grid layout container as the root node, and set the width of the scene to 300 pixels and the height to 400 pixels Scene scene = new Scene(gridPane, 320, 502); //Set the scene to the main stage primaryStage.setScene(scene); // Create an input text box and add it to the first row of the grid layout container inputField = createInputField(); gridPane.add(inputField, 0, 0, 4, 1); //Add a button to the specified position of the grid layout container addButtonToGrid(gridPane, "AC", 0, 1); addButtonToGrid(gridPane, "DEL", 1, 1); addButtonToGrid(gridPane, "(", 2, 1); addButtonToGrid(gridPane, ")", 3, 1); addButtonToGrid(gridPane, "7", 0, 2); addButtonToGrid(gridPane, "8", 1, 2); addButtonToGrid(gridPane, "9", 2, 2); addButtonToGrid(gridPane, "/", 3, 2); addButtonToGrid(gridPane, "4", 0, 3); addButtonToGrid(gridPane, "5", 1, 3); addButtonToGrid(gridPane, "6", 2, 3); addButtonToGrid(gridPane, "*", 3, 3); addButtonToGrid(gridPane, "1", 0, 4); addButtonToGrid(gridPane, "2", 1, 4); addButtonToGrid(gridPane, "3", 2, 4); addButtonToGrid(gridPane, "-", 3, 4); addButtonToGrid(gridPane, ".", 0, 5); addButtonToGrid(gridPane, "0", 1, 5); addButtonToGrid(gridPane, "00", 2, 5); addButtonToGrid(gridPane, " + ", 3, 5); addButtonToGrid(gridPane, "=", 3, 6, 2); primaryStage.show(); } private GridPane createGridPane() { //Create a grid layout container object GridPane gridPane = new GridPane(); // Set the horizontal spacing between columns in the grid layout container to 6 pixels gridPane.setHgap(6); // Set the vertical spacing between rows in the grid layout container to 9 pixels gridPane.setVgap(9); //Set the padding of the grid layout container to 10 pixels gridPane.setPadding(new Insets(10)); // Return the created grid layout container object return gridPane; } private TextField createInputField() { //Create a text box object TextField textField = new TextField(); // Actually, I don’t know how to adjust the position. I just searched the tutorial and found the code to adjust the position, and tried the data several times. textField.setStyle("-fx-alignment: bottom-left;"); textField.setStyle("-fx-padding: 0 0 -30 0;"); //Set the text box as non-editable textField.setEditable(false); // Set the preferred height of the text box to 125 pixels textField.setPrefHeight(125); // Set font size to 21 textField.setFont(Font.font(21)); // Return the created text box object return textField; } private void addButtonToGrid(GridPane gridPane, String text, int col, int row) { addButtonToGrid(gridPane, text, col, row, 1); } //Accepts an additional colSpan parameter, which is used to specify the number of columns that the button spans in the horizontal direction, and controls the horizontal space occupied by the button in the grid layout. private void addButtonToGrid(GridPane gridPane, String text, int col, int row, int colSpan) { //Create button and set button text Button button = new Button(text); //Set the handler of the button click event to the handleButtonAction method, passing the button text as a parameter button.setOnAction(e -> handleButtonAction(text)); //Set the preferred size of the button button.setPrefSize(70, 50); //Set font size to 16 button.setFont(Font.font(16)); //Add the button to the specified position in the grid layout gridPane.add(button, col, row, colSpan, 1); } private void handleButtonAction(String text) { switch (text) { case "=" -> { // When the "=" button is clicked, the result of the expression is calculated and displayed in the input box // The integer display problem that has been tormenting me for a long time, I have been changing it in evaluateExpression, but later I forgot to convert it to String. String expression = inputField.getText(); double result = evaluateExpression(expression); if (result % 1 == 0) { int intResult = (int) result; inputField.setText(String.valueOf(intResult)); } else { inputField.setText(String.valueOf(result)); } } case "AC" -> // Clear the input box when clicking the "AC" button inputField.clear(); case "DEL" -> { // When the "Delete" button is clicked, delete a character from the input box String currentText = inputField.getText(); if (!currentText.isEmpty()) { inputField.setText(currentText.substring(0, currentText.length() - 1)); } } default-> //Append the clicked button text to the input box inputField.appendText(text); } } private double evaluateExpression(String expression) { //Remove spaces from expression expression = expression.replaceAll("\s + ", ""); //Initialize operator stack and operand stack Stack<Character> operatorStack = new Stack<>(); Stack<Double> operandStack = new Stack<>(); //Define operator precedence 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 == '.') { // Process numbers StringBuilder sb = new StringBuilder(); i = getI(expression, operandStack, i, sb); } else if (ch == '(') { // handle left bracket operatorStack.push(ch); i + + ; } else if (ch == ')') { // Process the right bracket while (!operatorStack.isEmpty() & amp; & amp; operatorStack.peek() != '(') { applyOperator(operatorStack.pop(), operandStack, operatorStack); } operatorStack.pop(); // Pop the left bracket i + + ; } else if (isOperator(ch)) { // processing operator if (ch == '-' & amp; & amp; (i == 0 || expression.charAt(i - 1) == '(')) { // When the operator is a negative sign and is at the beginning of the expression or after the left parenthesis, push the negative sign onto the operand stack together with the operand i + + ; StringBuilder sb = new StringBuilder("-"); i = getI(expression, operandStack, i, sb); } else { while (!operatorStack.isEmpty() & amp; & amp; operatorStack.peek() != '(' & amp; & amp; precedence.get(ch) <= precedence.get(operatorStack.peek()) ) { //The operator is not a negative sign and meets the condition. Pop the operator on the top of the stack and apply it to the operand in the operand stack applyOperator(operatorStack.pop(), operandStack, operatorStack); } // Push the current operator onto the operator stack operatorStack.push(ch); i + + ; } } else { // Ignore other characters (such as spaces) i + + ; } } // Process remaining operators while (!operatorStack.isEmpty()) { applyOperator(operatorStack.pop(), operandStack, operatorStack); } //Return the final result if (!operandStack.isEmpty()) { return operandStack.pop(); } else { throw new IllegalArgumentException("Invalid expression"); } } private int getI(String expression, Stack<Double> operandStack, int i, StringBuilder sb) { // Starting from the current position, continuously obtain numeric characters or decimal point characters, and add them to the StringBuilder until a non-numeric non-decimal point character is encountered while (i < expression.length() & amp; & amp; (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) { sb.append(expression.charAt(i)); i + + ; } // Parse the string in StringBuilder into double type operands double operand = Double.parseDouble(sb.toString()); //Push the operand onto the operand stack operandStack.push(operand); // Return the updated position index return i; } private boolean isOperator(char ch) { return ch == ' + ' || ch == '-' || ch == '*' || ch == '/'; } private void applyOperator(char operator, Stack<Double> operandStack, Stack<Character> operatorStack) { if (operandStack.size() < 2) { // The number of operands in the operand stack is insufficient and the operation cannot be performed. throw new IllegalArgumentException("Invalid 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) { // Divisor is zero, exception throw new ArithmeticException("Division by zero"); } yield operand1 / operand2; } default -> 0; // By default, 0 is returned }; //Push the operation result onto the operand stack operandStack.push(result); // Handle negative results if (!operandStack.isEmpty() & amp; & amp; operandStack.peek() < 0) { if (!operatorStack.isEmpty()) { char nextOperator = operatorStack.peek(); if (nextOperator == ' + ' || nextOperator == '-') { // Convert the negative result to a negative number when the next operator is a plus or minus sign double negativeResult = operandStack.pop(); operandStack.push(-negativeResult); } } } } public static void main(String[] args) { launch(args); } }
The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 136733 people are learning the system