A crazy guy

Java实现MacOS计算器

full java calculator

起因

课程列表中有一门Java编程课程,其中有一个实验作业是模仿Windows自带的计算器做一个非常简单的计算器,但由于目前没有使用Windows,于是只能仿着MacOS自带的计算器实现了一个,初次接触Java,也初次接触swing。

功能

我没有具体研究过计算器的各项功能,仅凭自己简单的使用经验写了一个,具体实现以下功能。

  • 界面布局与MacOS基本一致
  • 0做除数的异常处理
  • 运算结果浮点数与整数的优化显示
  • 在触发操作符后数字闪烁一下已达到操作反馈交互
  • 实现任务栏图标的替换
  • 实现键盘输入的交互
  • 实现复制粘贴功能

代码

毕竟是初次接触Java,所以还是有不少可以继续学习提升的地方,另外写逻辑代码那部分其实还是可以在优化的,以后有机会吧,这个例子我花了五个小时,远超出我对一个计算器的理解了,写下来才发现算然计算器看着简单但也有很多细小的逻辑点,所以这个代码基本就处于没有经过仔细设计分析就按着感觉写,边写边改。

虽然还有很多有待改进的地方,但它的完成度很高。

Calculator.java

package com.nicholas;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.io.IOException;
import java.util.Arrays;

public class Calculator {

  private String[] operations = {"/", "*", "-", "+", "="};
  private String[] numbers = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
  private String last_result = "";
  private String last_input = "";
  private String last_operation = "";
  private String current_operation = "";
  private String version = "1.0";

  private JMenu edit_menu;
  private JMenu help_menu;
  

  // 设置这个值主要是为了单元测试
  private String current_text = "0";

  private Boolean start_number_input = true;
  private JButton[] bs = new JButton[19];
  private JTextField answer_field = new JTextField();

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

  Calculator() {
    JFrame frame = new JFrame("Calculator");
    Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
    int height = screen_size.height;
    int width = screen_size.width;
    frame.pack();

    // 设置关闭窗口时退出程序,相当于System.exit(0)
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    // 设置窗体大小和位置
    frame.setSize(250, 350);
    frame.setLocation(width/2 - frame.getSize().width/2, height/2 - frame.getSize().height);

    // 文本框默认显示0
    answer_field.setText("0");
    answer_field.setHorizontalAlignment(JTextField.RIGHT);
    

    GridBagLayout gbl = new GridBagLayout();
    JPanel panel = new JPanel(gbl);
    panel.setLayout(gbl);

    // 绘制按钮布局
    String[] buttons = {
      "AC", "+/-", "%", "/", 
      "7", "8", "9", "*",
      "4", "5", "6", "-",
      "1", "2", "3", "+",
      "0", ".", "=",
    };

    for (int i = 0; i < buttons.length; i++) {
      bs[i] = new JButton(buttons[i]);
      bs[i].setFocusPainted(false);
    }

    GridBagConstraints gbc = new GridBagConstraints();

    gbc.fill = GridBagConstraints.BOTH;
    gbc.weightx=1;
    gbc.weighty=1;
    gbc.gridwidth = 3;
    gbc.gridheight = 1;

    for (int i = 0; i < bs.length; i++) {
      if ((i + 1) % 4 == 0) {
        gbc.gridwidth = GridBagConstraints.REMAINDER;
      } else if (buttons[i].equals("0")) {
        // 0跨2列
        gbc.gridwidth = 2;
      } else {
        gbc.gridwidth = 1;
      }
      gbl.setConstraints(bs[i], gbc);
      panel.add(bs[i]);
    }

    // 给按钮添加监听事件
    for (int i = 0; i < bs.length; i++) {
      JButton button = bs[i];
      button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          JButton source_button = (JButton) e.getSource();
          String input_text = source_button.getText();
          blink_button(source_button);
          handle_input(input_text);
        }
      });
    }

    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
      @Override
      public boolean dispatchKeyEvent(KeyEvent e) {
        if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_C && e.isMetaDown()) {
          copy_to_clipboard(current_text);
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_V && e.isMetaDown()) {
          paste_from_clipboard();
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_A && e.isMetaDown()) {
          show_about_dialog();
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_E && e.isMetaDown()) {
          edit_menu.setPopupMenuVisible(true);
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_H && e.isMetaDown() && e.isShiftDown()) {
          help_menu.doClick();
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
          handle_input("b");
          return true;
        } else if (
          e.getID() == KeyEvent.KEY_PRESSED && 
          (e.getKeyCode() == KeyEvent.VK_ENTER || (e.getKeyCode() == KeyEvent.VK_EQUALS && !e.isShiftDown()))
        ) {
          handle_input("=");
          blink_button(get_button_by_input("="));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ESCAPE) {
          handle_input("ac");
          blink_button(get_button_by_input("ac"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_K) {
          handle_input("c");
          blink_button(get_button_by_input("ac"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_N) {
          handle_input("+/-");
          blink_button(get_button_by_input("+/-"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_PERIOD) {
          handle_input(".");
          blink_button(get_button_by_input("."));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_SLASH) {
          handle_input("/");
          blink_button(get_button_by_input("/"));
          return true;
        } else if (
          (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_ASTERISK)
          || (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_8 && e.isShiftDown())
        ) {
          handle_input("*");
          blink_button(get_button_by_input("*"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_MINUS) {
          handle_input("-");
          blink_button(get_button_by_input("-"));
          return true;

        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_5 && e.isShiftDown()) {  
          handle_input("%");
          blink_button(get_button_by_input("%"));
          return true;
        } else if (
          (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_EQUALS)
          || (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_EQUALS && e.isShiftDown())
        ) {
          handle_input("+");
          blink_button(get_button_by_input("+"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_0) {
          handle_input("0");
          blink_button(get_button_by_input("0"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_1) {
          handle_input("1");
          blink_button(get_button_by_input("1"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_2) {
          handle_input("2");
          blink_button(get_button_by_input("2"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_3) {
          handle_input("3");
          blink_button(get_button_by_input("3"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_4) {
          handle_input("4");
          blink_button(get_button_by_input("4"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_5) {
          handle_input("5");
          blink_button(get_button_by_input("5"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_6) {
          handle_input("6");
          blink_button(get_button_by_input("6")); 
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_7) {
          handle_input("7");
          blink_button(get_button_by_input("7"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_8) {
          handle_input("8");
          blink_button(get_button_by_input("8"));
          return true;
        } else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_9) {
          handle_input("9");
          blink_button(get_button_by_input("9"));
          return true;
        }
        return false;
      }
    });

    Font font = new Font("Arial", Font.PLAIN, 40);
    
    answer_field.setEditable(false);
    answer_field.setFont(font);

    frame.add(answer_field, BorderLayout.NORTH);
    frame.add(panel, BorderLayout.CENTER);

    // 设置窗体图标
    try {
      Image icon = ImageIO.read(getClass().getResource("/calc.png"));
      Taskbar.getTaskbar().setIconImage(icon);
      frame.setIconImage(icon);
    } catch (IOException e) {
      e.printStackTrace();
    }
    

    // 菜单
    // 让菜单栏显示在顶部
    System.setProperty("apple.laf.useScreenMenuBar", "true");
    System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Stack");

    JMenuBar menu_bar = new JMenuBar();

    edit_menu = new JMenu("编辑(E)");

    JMenuItem copy_item = new JMenuItem("复制(C) Cmd + C");

    copy_item.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        copy_to_clipboard(current_text);
      }
    });

    JMenuItem paste_item = new JMenuItem("粘贴(P) Cmd + V");

    // 如何实现粘贴功能
    paste_item.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        paste_from_clipboard();
      }
    });

    
    edit_menu.add(copy_item);
    edit_menu.add(paste_item);
    
    help_menu = new JMenu("帮助(H)");
    JMenuItem about_item = new JMenuItem("关于(A) Cmd + A");

    about_item.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        show_about_dialog();
      }
    });

    help_menu.add(about_item);
    
    menu_bar.add(edit_menu);
    menu_bar.add(help_menu);
    
    frame.setJMenuBar(menu_bar);


    frame.setFocusable(true);
    frame.requestFocusInWindow();
    frame.setVisible(true);
  }

  private String calculateResult(String operator, String operand1, String operand2) {
    double num1;
    double num2;

    if (operand1.equals("Infinity") || operand2.equals("Infinity")) {
      return "Not a number";
    }

    try {
      num1 = Double.parseDouble(operand1);
      num2 = Double.parseDouble(operand2);
    } catch (IllegalArgumentException e) {
      return "Not a number";
    }

    double result;

    switch (operator) {
      case "/":
        if (num2 == 0) {
          return "Infinity";
        } else {
          result = num1 / num2;
        }
        break;
      case "*":
        result = num1 * num2;
        break;
      case "-":
        result = num1 - num2;
        break;
      case "+":
        result = num1 + num2;
        break;
      default:
        throw new IllegalArgumentException("Invalid operator: " + operator);
    }

    if (result == Math.floor(result)) {
      return String.valueOf((int) result);
    } else {
      return String.valueOf(result);
    }
  }

  public void handle_input(String input_text) {

    // 全部清空
    if (input_text.toLowerCase().equals("ac")) {

      set_answer_text("0");
      blink_answer_text();
      last_result = "";
      last_operation = "";
      last_input = "";
      current_operation = "";
      bs[0].setText("AC");

    // 清空当前输入
    } else if (input_text.toLowerCase().equals("c")) {

      if (start_number_input && !current_operation.equals("")) {
        current_operation = "";
        blink_answer_text();
      } else {
        set_answer_text("0");
      }
      
      bs[0].setText("AC");

    // 退格
    } else if (input_text.toLowerCase().equals("b")) {

      if (current_text.length() == 1) {
        current_text = "0";
      } else {
        current_text = current_text.substring(0, current_text.length() - 1);
      }

      answer_field.setText(current_text);

    // 正负号
    } else if (input_text.equals("+/-")) {
      if (current_text.equals("0")) {
        return;
      }

      bs[0].setText("C");

      if (current_text.startsWith("-")) {
        current_text = current_text.substring(1);
      } else {
        current_text = "-" + current_text;
      }

      answer_field.setText(current_text);

    // 百分号
    } else if (input_text.equals("%")) {
      if (current_text.equals("0")) {
        return;
      }

      bs[0].setText("C");

      double num = Double.parseDouble(current_text);
      num = num / 100;
      set_answer_text(String.valueOf(num));

    // 运算符
    } else if (Arrays.asList(operations).contains(input_text)) {
      start_number_input = true;
      bs[0].setText("C");

      // 等号运算符处理
      if (input_text.equals("=")) {

        // 执行重复等号计算
        if (current_operation.equals("") && !last_result.equals("") && !last_operation.equals("") && !last_input.equals("")) {
          String result = calculateResult(last_operation, last_result, last_input);
          last_result = result;
          set_answer_text(result);
          
        // 执行普通等号计算
        } else if (!current_operation.equals("") && !last_input.equals("")) {
          String result = calculateResult(current_operation, last_result, current_text);
          last_input = current_text;
          set_answer_text(result);
          last_result = result;
          last_operation = current_operation;
          current_operation = "";
        }

      } else {
      
        // 如果前面没有输入过运算符,直接保存当前输入的运算符
        if (start_number_input && current_operation.equals("")) {

          last_input = current_text;
          last_result = current_text;
          current_operation = input_text;
          blink_answer_text();

        // 如果前面输入过运算符,先计算前面的运算符
        } else {
          String result = calculateResult(current_operation, last_result, current_text);
          set_answer_text(result);
          last_result = result;
          last_input = current_text;
          last_operation = current_operation;
          current_operation = input_text;
        }
      }

    // 小数点
    } else if (input_text.equals(".")) {
      bs[0].setText("C");

      if (current_text.contains(".")) {
        return;
      }

      start_number_input = false;
      current_text += ".";
      answer_field.setText(current_text);

    // 数字
    } else if (Arrays.asList(numbers).contains(input_text)) {
      bs[0].setText("C");

      if (current_text.equals("0") || start_number_input) {
        current_text = input_text;
      } else {
        current_text += input_text;
      }

      answer_field.setText(current_text);
      start_number_input = false;

    }

  }


  private void set_answer_text(String text) {
    current_text = text;
    answer_field.setText(current_text);
  }


  // 闪烁答案文本,主要是为了交互效果
  private void blink_answer_text() {
    answer_field.setText("");

    Timer timer = new Timer(40, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            answer_field.setText(current_text);
          }
        });
      }
    });

    timer.setRepeats(false);
    timer.start();
  }

  // 根据输入文本获取按钮
  private JButton get_button_by_input(String input_text) {
    for (JButton button : bs) {
      if (button.getText().toLowerCase().equals(input_text)) {
        return button;
      }
    }

    return null;
  }

  // 闪烁按钮,主要是为了交互效果
  private void blink_button(JButton button) {
    button.setOpaque(true);
    button.setContentAreaFilled(true);
    button.setBackground(Color.GRAY);

    Timer timer = new Timer(40, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            button.setOpaque(true);
            button.setContentAreaFilled(true);
            button.setBackground(null);
          }
        });
      }
    });

    timer.setRepeats(false);
    timer.start();
  }

  private void copy_to_clipboard(String text) {
    StringSelection stringSelection = new StringSelection(text);
    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    clipboard.setContents(stringSelection, null);
  }

  private void paste_from_clipboard() {
    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    String result = "";
    try {
      result = (String) clipboard.getData(DataFlavor.stringFlavor);
    } catch (Exception e) {
      e.printStackTrace();
      return;
    }

    // 如果粘贴的内容是数字,直接替换当前文本
    if (!result.matches("^-?\\d+(\\.\\d+)?$")) {
      return;
    }

    set_answer_text(result);
  }

  private void show_about_dialog() {
    String body[] = {
      "<html>",
      "<h1>计算器</h1>",
      "<p></p>",
      "<p>这是一个简单的计算器,模仿MacOS自带的计算器,它具备常用的计算器功能可以进行加减乘除等。</p>",
      "<p>如果你有任何问题或者建议,欢迎联系我。</p>",
      "<p></p>",
      "<p></p>",
      "<p>作者: Nicholas Lee</p>",
      "<p>版本: " + version + "</p>",
      "</html>"
    };
    JOptionPane.showMessageDialog(null, String.join("", body), "关于", JOptionPane.INFORMATION_MESSAGE);
  }

  public String get_current_text() {
    return current_text;
  }
}

CalculatorTest.java

package com.nicholas;

import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

public class CalculatorTest {
  @Test
  public void testNormal() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("12", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("12", calculator.get_current_text());

    calculator.handle_input("3");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("15", calculator.get_current_text());
  }

  @Test
  public void testClear() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("12", calculator.get_current_text());

    calculator.handle_input("C");
    assertEquals("0", calculator.get_current_text());
  }

  @Test
  public void testZeroNegative() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("+/-");
    assertEquals("0", calculator.get_current_text());
  }

  @Test
  public void testNegative() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("-1", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("1", calculator.get_current_text());
  }

  @Test
  public void testPercentage() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("0");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("%");
    assertEquals("0.1", calculator.get_current_text());
  }

  @Test
  public void testDotInput() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input(".");
    assertEquals("0.", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("0.1", calculator.get_current_text());

    calculator.handle_input("5");
    assertEquals("0.15", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("0.15", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperations() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("7", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperationsWithClear() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("C");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());
  }
  
  @Test
  public void testMultipleOperationsWithNegative() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("-3", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("-3", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("1", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperationsWithPercentage() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("%");
    assertEquals("0.03", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("0.03", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("4.03", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperationsWithNegativeAndPercentage() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("-3", calculator.get_current_text());

    calculator.handle_input("%");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3.97", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperationsWithClearAndNegativeAndPercentage() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("-3", calculator.get_current_text());

    calculator.handle_input("%");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3.97", calculator.get_current_text());

    calculator.handle_input("C");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperationsWithClearAndNegativeAndPercentageAndMultipleOperations() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("-3", calculator.get_current_text());

    calculator.handle_input("%");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3.97", calculator.get_current_text());

    calculator.handle_input("C");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("7", calculator.get_current_text());
  }

  @Test
  public void testMultipleOperationsWithClearAndNegativeAndPercentageAndMultipleOperationsAndClear() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+/-");
    assertEquals("-3", calculator.get_current_text());

    calculator.handle_input("%");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("-0.03", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3.97", calculator.get_current_text());

    calculator.handle_input("C");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("7", calculator.get_current_text());

    calculator.handle_input("C");
    assertEquals("0", calculator.get_current_text());
  }

  @Test
  public void testAutoCalculateWithNotEqualOperations() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("4");
    assertEquals("4", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("7", calculator.get_current_text());
  }

  @Test
  public void testChangeOperations() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("0");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("c");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("*");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("5");
    assertEquals("5", calculator.get_current_text());

    calculator.handle_input("0");
    assertEquals("50", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("500", calculator.get_current_text());
  }

  @Test
  public void testZeroDivision() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("/");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("0");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("Infinity", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("Infinity", calculator.get_current_text());

    calculator.handle_input("9");
    assertEquals("9", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("Not a number", calculator.get_current_text());

  }

  @Test
  public void testRepearEqualOperation() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("+");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("2", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("3", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("5", calculator.get_current_text());

    calculator.handle_input("/");
    assertEquals("5", calculator.get_current_text());

    calculator.handle_input("c");
    assertEquals("5", calculator.get_current_text());

    calculator.handle_input("*");
    assertEquals("5", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("0");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("-");
    assertEquals("50", calculator.get_current_text());

    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("0");
    assertEquals("10", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("40", calculator.get_current_text());

    calculator.handle_input("=");
    assertEquals("30", calculator.get_current_text());
  }

  @Test
  public void testBackspace() throws Exception {
    Calculator calculator = new Calculator();

    assertEquals("0", calculator.get_current_text());

    // Add your tests here
    calculator.handle_input("1");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("2");
    assertEquals("12", calculator.get_current_text());

    calculator.handle_input("b");
    assertEquals("1", calculator.get_current_text());

    calculator.handle_input("b");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input("b");
    assertEquals("0", calculator.get_current_text());

    calculator.handle_input(".");
    assertEquals("0.", calculator.get_current_text());

    calculator.handle_input("9");
    assertEquals("0.9", calculator.get_current_text());

    calculator.handle_input("b");
    assertEquals("0.", calculator.get_current_text());

    calculator.handle_input("b");
    assertEquals("0", calculator.get_current_text());

  }
}
分享

TITLE: Java实现MacOS计算器

LINK: https://www.qttc.net/563-java-exercice-calculator.html

NOTE: 原创内容,转载请注明出自琼台博客