首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Swing 簡易計算機完整實作:從介面佈局到四則運算邏輯

     編輯:Java 相關知識

前言

計算機 是 GUI 程式設計的經典入門專案,涵蓋事件驅動模型、佈局管理、狀態管理等核心概念。本文使用 Java Swing 實作一個支援加減乘除、小數點、退位、平方根等功能的桌面計算機。

介面設計與佈局規劃

┌─────────────────────┐
│  顯示區域 (JTextField)  │  ← 右對齊,唯讀
├─────────────────────┤
│  7  │  8  │  9  │  ÷  │
├─────┼─────┼─────┼─────┤
│  4  │  5  │  6  │  ×  │
├─────┼─────┼─────┼─────┤
│  1  │  2  │  3  │  -  │
├─────┼─────┼─────┼─────┤
│  0  │  .  │  ←  │  +  │
├─────┼─────┼─────┼─────┤
│     C     │  √  │  =  │
└─────────────────────┘

完整程式碼實作

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Calculator extends JFrame implements ActionListener {
    private JTextField display;
    private JButton[] numberButtons = new JButton[10];
    private JButton[] operatorButtons = new JButton[4];
    private JButton btnDot, btnEqual, btnClear, btnBack, btnSqrt;
    private JPanel panel;

    // 運算狀態
    private double operand1 = 0;
    private double operand2 = 0;
    private int operator = -1; // 0:+, 1:-, 2:*, 3:/
    private boolean isNewInput = true;

    public Calculator() {
        super("Java 簡易計算機");
        setSize(320, 420);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setResizable(false);
        initComponents();
        setVisible(true);
    }

    private void initComponents() {
        // 顯示欄位
        display = new JTextField("0");
        display.setFont(new Font("Consolas", Font.BOLD, 28));
        display.setHorizontalAlignment(JTextField.RIGHT);
        display.setEditable(false);
        display.setBackground(Color.WHITE);
        display.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        add(display, BorderLayout.NORTH);

        // 按鈕面板 - GridLayout 4行4列
        panel = new JPanel(new GridLayout(5, 4, 5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 數字鍵 0-9
        for (int i = 0; i < 10; i++) {
            numberButtons[i] = new JButton(String.valueOf(i));
            numberButtons[i].setFont(new Font("微軟正黑體", Font.BOLD, 20));
            numberButtons[i].addActionListener(this);
        }

        // 運算子鍵
        String[] ops = {"+", "-", "×", "÷"};
        for (int i = 0; i < 4; i++) {
            operatorButtons[i] = new JButton(ops[i]);
            operatorButtons[i].setFont(new Font("微軟正黑體", Font.BOLD, 20));
            operatorButtons[i].setBackground(new Color(240, 240, 240));
            operatorButtons[i].addActionListener(this);
        }

        // 功能鍵
        btnDot = createFuncButton(".");
        btnEqual = createFuncButton("=");
        btnClear = createFuncButton("C");
        btnBack = createFuncButton("←");
        btnSqrt = createFuncButton("√");

        // 佈局排列 (按視覺順序加入 panel)
        // 第1行: 7 8 9 ÷
        addButtons(7, 8, 9, 3);
        // 第2行: 4 5 6 ×
        addButtons(4, 5, 6, 2);
        // 第3行: 1 2 3 -
        addButtons(1, 2, 3, 1);
        // 第4行: 0 . ← +
        addButtons(0, -1, -2, 0); // -1=dot, -2=back
        // 第5行: C √ = (佔兩格)
        panel.add(btnClear);
        panel.add(btnSqrt);
        panel.add(btnEqual);
        panel.add(new JLabel()); // 佔位

        add(panel, BorderLayout.CENTER);
    }

    private JButton createFuncButton(String text) {
        JButton btn = new JButton(text);
        btn.setFont(new Font("微軟正黑體", Font.BOLD, 20));
        btn.setBackground(new Color(220, 230, 241));
        btn.addActionListener(this);
        return btn;
    }

    private void addButtons(int n1, int n2, int n3, int opIndex) {
        panel.add(numberButtons[n1]);
        if (n2 == -1) panel.add(btnDot);
        else if (n2 == -2) panel.add(btnBack);
        else panel.add(numberButtons[n2]);
        
        if (n3 == -1) panel.add(btnDot);
        else if (n3 == -2) panel.add(btnBack);
        else panel.add(numberButtons[n3]);
        
        panel.add(operatorButtons[opIndex]);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object src = e.getSource();

        // 數字鍵處理
        for (int i = 0; i < 10; i++) {
            if (src == numberButtons[i]) {
                handleNumberInput(i);
                return;
            }
        }

        // 小數點
        if (src == btnDot) {
            handleDotInput();
            return;
        }

        // 退位鍵
        if (src == btnBack) {
            handleBackspace();
            return;
        }

        // 清除鍵
        if (src == btnClear) {
            clearAll();
            return;
        }

        // 平方根
        if (src == btnSqrt) {
            handleSqrt();
            return;
        }

        // 運算子鍵
        for (int i = 0; i < 4; i++) {
            if (src == operatorButtons[i]) {
                handleOperator(i);
                return;
            }
        }

        // 等號鍵
        if (src == btnEqual) {
            handleEqual();
        }
    }

    private void handleNumberInput(int num) {
        String current = display.getText();
        if (isNewInput || current.equals("0") || current.equals("錯誤")) {
            display.setText(String.valueOf(num));
            isNewInput = false;
        } else {
            display.setText(current + num);
        }
    }

    private void handleDotInput() {
        String current = display.getText();
        if (isNewInput) {
            display.setText("0.");
            isNewInput = false;
        } else if (!current.contains(".")) {
            display.setText(current + ".");
        }
    }

    private void handleBackspace() {
        String current = display.getText();
        if (current.length() > 1 && !current.equals("錯誤")) {
            display.setText(current.substring(0, current.length() - 1));
        } else {
            display.setText("0");
            isNewInput = true;
        }
    }

    private void clearAll() {
        display.setText("0");
        operand1 = operand2 = 0;
        operator = -1;
        isNewInput = true;
    }

    private void handleSqrt() {
        try {
            double val = Double.parseDouble(display.getText());
            if (val < 0) throw new ArithmeticException("負數無平方根");
            display.setText(formatResult(Math.sqrt(val)));
            isNewInput = true;
        } catch (NumberFormatException ex) {
            display.setText("錯誤");
        }
    }

    private void handleOperator(int op) {
        try {
            double currentVal = Double.parseDouble(display.getText());
            
            if (operator != -1 && !isNewInput) {
                // 連續運算:先計算前一個運算
                handleEqual();
                currentVal = Double.parseDouble(display.getText());
            }
            
            operand1 = currentVal;
            operator = op;
            isNewInput = true;
        } catch (NumberFormatException ex) {
            display.setText("錯誤");
        }
    }

    private void handleEqual() {
        if (operator == -1) return; // 沒有待執行運算
        
        try {
            operand2 = Double.parseDouble(display.getText());
            double result = 0;
            
            switch (operator) {
                case 0: result = operand1 + operand2; break;
                case 1: result = operand1 - operand2; break;
                case 2: result = operand1 * operand2; break;
                case 3: 
                    if (operand2 == 0) {
                        display.setText("錯誤:除以零");
                        return;
                    }
                    result = operand1 / operand2; 
                    break;
            }
            
            display.setText(formatResult(result));
            operator = -1;
            isNewInput = true;
        } catch (NumberFormatException ex) {
            display.setText("錯誤");
        }
    }

    private String formatResult(double value) {
        // 整數顯示為無小數點,浮點數保留合理精度
        if (value == (long) value) {
            return String.format("%d", (long) value);
        } else {
            return String.format("%.10f", value).replaceAll("0*$", "").replaceAll("\\.$", "");
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Calculator());
    }
}

核心邏輯解析

狀態機設計

計算機核心是一個有限狀態機,關鍵狀態變數:

  • operand1:第一運算元(暫存結果)
  • operator:待執行運算子(-1 表示無)
  • isNewInput:標記下一個輸入是否為新數字起始

連續運算處理

使用者輸入 3 + 4 × 5 = 時,採用即時運算邏輯(非科學計算機的優先級邏輯):

  1. 輸入 3,按 + → operand1=3, operator=+
  2. 輸入 4,按 × → 先執行 3+4=7,operand1=7, operator=×
  3. 輸入 5,按 = → 執行 7×5=35

錯誤處理策略

  • 除以零 → 顯示錯誤訊息,鎖定輸入直到按 C
  • 負數開根號 → 顯示錯誤
  • 格式錯誤 → 顯示「錯誤」,下一輸入自動重置

進階擴展方向

  • 科學計算機模式:加入 sin/cos/tan、log、指數、常數 π、e
  • 歷史記錄:使用 JList 或 JTextArea 記錄運算歷程
  • 鍵盤支援:實作 KeyListener 對應數字鍵盤輸入
  • 主題切換:支援淺色/深色模式切換
  • 單位轉換:長度、重量、溫度、貨幣換算
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved