🤔 还在羡慕别人家的炫酷计算器?为什么不用Java Swing打造一个属于自己的计算神器呢?

181 阅读18分钟

🏆本文收录于「滚雪球学SpringBoot」(全网一个名)专栏,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

📝 前言:一次意外的编程冒险

  哈哈,说起这个Java计算器项目,还真是有点故事呢!😄 那是去年夏天的一个闷热午后,我正在家里无聊地刷着技术博客,突然看到一个朋友在朋友圈晒他用Python写的计算器,界面做得还挺漂亮的。当时我就想,"切,Python能做的,Java也能做啊!而且还能做得更好看!"

  于是乎,我这个倔强的Java党就开始了一场与Swing的"爱恨情仇"之旅。说实话,刚开始真的是各种踩坑,从布局管理器到事件监听,从界面美化到功能实现,每一步都让我欲哭无泪。但是,当我看到最终那个漂亮的计算器界面在屏幕上闪闪发光时,那种成就感真的是无法用言语形容!💪

  今天,我就想把这个项目的全部经验和心得分享给大家,希望能让更多朋友感受到GUI编程的魅力,也让大家避开我曾经踩过的那些坑!相信我,看完这篇文章,你一定能做出一个让自己满意的计算器!🎯

如下是正常运行起来的计算器V1.0版本,先给大家过过眼~

有人可能会问,简单加减乘除这谁不会,当然,若我把科学计算器也集中进去,那你可否接的住招?

🎨 为什么选择Swing?别急,听我慢慢道来

💡 Swing的独特魅力

  说到Java的GUI开发,很多人第一反应可能是"哎呀,现在都什么年代了,还用Swing?"但是朋友们,你们可别小看了Swing!虽然它确实有些年头了,但在某些场景下,它的优势真的很明显:

1. 跨平台特性

// 一次编写,到处运行,这不就是Java的精髓吗?
public static void main(String[] args) {
    // 设置系统外观
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel());
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    SwingUtilities.invokeLater(() -> {
        new Calculator().setVisible(true);
    });
}

  你看,同一份代码在Windows、Mac、Linux上都能跑,而且还能自动适应系统的外观风格。这种"一劳永逸"的感觉,真的很爽!😎

2. 丰富的组件库

  Swing提供的组件真的很丰富,从基本的JButton、JTextField到复杂的JTable、JTree,基本上你能想到的界面元素都有现成的。而且,自定义能力也很强,想要什么效果基本都能实现!

3. 事件处理机制

  Swing的事件处理机制真的设计得很优雅,监听器模式用得炉火纯青。我第一次理解设计模式的精髓,就是通过Swing的事件处理!

🤷‍♂️ 当然,坑也不少

  不过说实话,Swing也确实有一些让人头疼的地方:

  • 界面美化比较困难:默认的外观确实有点丑
  • 学习曲线较陡:布局管理器什么的,新手确实容易懵
  • 性能问题:复杂界面确实可能有性能瓶颈

  但是!这些问题都不是无解的,关键是要找到正确的方法。接下来,我就把我的"独门秘籍"分享给大家!🔥

🏗️ 界面设计:让你的计算器颜值爆表

🎯 整体布局规划

  做GUI开发,最重要的就是先有个清晰的布局规划。我这个计算器的整体布局是这样设计的:

public class Calculator extends JFrame {
    private JTextField display;          // 显示屏
    private JPanel buttonPanel;          // 按钮面板
    private JPanel topPanel;             // 顶部面板
    
    public Calculator() {
        initializeComponents();
        setupLayout();
        setupEventHandlers();
        setupKeyBindings();
        
        setTitle("🧮 我的超级计算器");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        pack();
        setLocationRelativeTo(null);
    }
}

  看到没,我把整个界面分成了几个部分:显示屏、按钮面板、顶部面板。这种分层设计的思想,在GUI开发中真的很重要!

再比如,我还加上了主题与科学计算器的切换,大大增加了个人化。

📱 显示屏设计

  计算器的显示屏可是门面担当,必须得做得漂亮!

private void initializeDisplay() {
    display = new JTextField("0");
    display.setEditable(false);
    display.setHorizontalAlignment(JTextField.RIGHT);
    display.setFont(new Font("Monospaced", Font.BOLD, 24));
    display.setBackground(new Color(240, 240, 240));
    display.setBorder(BorderFactory.createCompoundBorder(
        BorderFactory.createRaisedBevelBorder(),
        BorderFactory.createEmptyBorder(10, 10, 10, 10)
    ));
    
    // 设置显示屏高度
    display.setPreferredSize(new Dimension(300, 60));
}

  这里有几个小技巧:

  1. 右对齐显示:数字显示右对齐,符合用户习惯
  2. 等宽字体:用Monospaced字体,数字显示更整齐
  3. 边框效果:复合边框让显示屏更有立体感
  4. 颜色搭配:浅灰色背景,看起来更舒服

🔘 按钮设计的艺术

  按钮设计真的是个技术活!既要好看,又要好用,还要有个性:

private JButton createStyledButton(String text, Color bgColor, Color fgColor) {
    JButton button = new JButton(text);
    button.setFont(new Font("Arial", Font.BOLD, 16));
    button.setBackground(bgColor);
    button.setForeground(fgColor);
    button.setFocusPainted(false);
    button.setBorderPainted(false);
    button.setOpaque(true);
    
    // 添加鼠标悬停效果
    button.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseEntered(MouseEvent e) {
            button.setBackground(bgColor.brighter());
        }
        
        @Override
        public void mouseExited(MouseEvent e) {
            button.setBackground(bgColor);
        }
    });
    
    return button;
}

  哇,这个悬停效果真的很赞!鼠标移上去按钮会变亮一点,用户体验瞬间提升!😍

🎨 布局管理器的选择

  说到布局管理器,这真的是Swing的精华所在。对于计算器这种规整的界面,我选择了GridLayout:

private void setupButtonLayout() {
    buttonPanel = new JPanel(new GridLayout(5, 4, 5, 5));
    buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    
    // 按钮文本数组
    String[] buttonTexts = {
        "C", "±", "%", "÷",
        "7", "8", "9", "×",
        "4", "5", "6", "-",
        "1", "2", "3", "+",
        "0", ".", "=", "⌫"
    };
    
    // 创建按钮并添加到面板
    for (String text : buttonTexts) {
        JButton button = createCalculatorButton(text);
        buttonPanel.add(button);
        buttons.put(text, button);
    }
}

  GridLayout的好处就是能让所有按钮大小一致,排列整齐。而且,设置了5像素的间距,看起来不会太拥挤。

⚡ 核心功能实现:让计算器真正"能算"

🧮 基本运算逻辑

  好看的界面有了,但如果不能算数,那就是个花瓶!计算器的核心逻辑其实并不复杂:

public class CalculatorEngine {
    private double firstOperand = 0;
    private double secondOperand = 0;
    private String currentOperator = "";
    private boolean isNewCalculation = true;
    private boolean operatorPressed = false;
    
    public double calculate(double first, double second, String operator) {
        switch (operator) {
            case "+":
                return first + second;
            case "-":
                return first - second;
            case "×":
                return first * second;
            case "÷":
                if (second == 0) {
                    throw new ArithmeticException("除数不能为零!这可是数学常识啊!😅");
                }
                return first / second;
            case "%":
                return first % second;
            default:
                return second;
        }
    }
}

  看,我还加了个除零检查,连错误提示都这么有个性!😄 这种细节的处理,真的能让用户感受到开发者的用心。

🔄 状态管理的智慧

  计算器的状态管理真的是个技术活。什么时候该清空显示,什么时候该准备下一次计算,这些逻辑都需要仔细考虑:

private void handleNumberInput(String number) {
    String currentText = display.getText();
    
    if (isNewCalculation || currentText.equals("0")) {
        display.setText(number);
        isNewCalculation = false;
    } else if (operatorPressed) {
        display.setText(number);
        operatorPressed = false;
    } else {
        display.setText(currentText + number);
    }
}

private void handleOperatorInput(String operator) {
    if (!operatorPressed) {
        if (!currentOperator.isEmpty()) {
            calculateResult();
        } else {
            firstOperand = Double.parseDouble(display.getText());
        }
    }
    
    currentOperator = operator;
    operatorPressed = true;
    isNewCalculation = false;
}

  这个状态管理逻辑,我可是调试了好久才搞定的!主要是要处理各种边界情况,比如连续按运算符、运算后继续计算等等。

✨ 特殊功能的实现

  除了基本的加减乘除,我还实现了一些特殊功能:

private void handleSpecialFunction(String function) {
    String currentText = display.getText();
    double currentValue = Double.parseDouble(currentText);
    
    switch (function) {
        case "C":
            // 全清除
            display.setText("0");
            firstOperand = 0;
            secondOperand = 0;
            currentOperator = "";
            isNewCalculation = true;
            operatorPressed = false;
            break;
            
        case "±":
            // 正负号切换
            if (currentValue != 0) {
                display.setText(String.valueOf(-currentValue));
            }
            break;
            
        case "⌫":
            // 退格
            if (currentText.length() > 1) {
                display.setText(currentText.substring(0, currentText.length() - 1));
            } else {
                display.setText("0");
            }
            break;
    }
}

  这些小功能看似简单,但实现起来还是有很多细节要考虑的。比如退格功能,要判断是不是只剩一位数,正负号切换要判断是不是零等等。

🎮 事件处理:让界面"活"起来

👆 鼠标点击事件

  按钮点击事件是GUI程序的基础,但怎么写得优雅,这就是技术活了:

private void setupButtonEvents() {
    for (Map.Entry<String, JButton> entry : buttons.entrySet()) {
        String buttonText = entry.getKey();
        JButton button = entry.getValue();
        
        button.addActionListener(e -> {
            handleButtonClick(buttonText);
            // 添加点击音效(如果需要的话)
            playClickSound();
        });
    }
}

private void handleButtonClick(String buttonText) {
    try {
        if (buttonText.matches("[0-9]")) {
            handleNumberInput(buttonText);
        } else if (buttonText.equals(".")) {
            handleDecimalInput();
        } else if (buttonText.matches("[+\\-×÷%]")) {
            handleOperatorInput(buttonText);
        } else if (buttonText.equals("=")) {
            calculateResult();
        } else {
            handleSpecialFunction(buttonText);
        }
    } catch (Exception ex) {
        display.setText("错误:" + ex.getMessage());
        isNewCalculation = true;
    }
}

  看到没,我用正则表达式来判断按钮类型,这样代码更简洁,维护也更方便。而且还加了异常处理,防止程序崩溃!

⌨️ 键盘事件支持

  现在的用户都很挑剔的,不支持键盘操作的计算器,体验就打折扣了!

private void setupKeyBindings() {
    // 数字键绑定
    for (int i = 0; i <= 9; i++) {
        final String num = String.valueOf(i);
        getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
            .put(KeyStroke.getKeyStroke(Character.forDigit(i, 10)), "number" + i);
        getRootPane().getActionMap().put("number" + i, 
            new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    handleButtonClick(num);
                }
            });
    }
    
    // 运算符键绑定
    setupOperatorKeyBindings();
    
    // 特殊键绑定
    setupSpecialKeyBindings();
}

private void setupOperatorKeyBindings() {
    Map<String, String> keyMappings = new HashMap<>();
    keyMappings.put("PLUS", "+");
    keyMappings.put("MINUS", "-");
    keyMappings.put("MULTIPLY", "×");
    keyMappings.put("DIVIDE", "÷");
    keyMappings.put("ENTER", "=");
    keyMappings.put("EQUALS", "=");
    
    for (Map.Entry<String, String> mapping : keyMappings.entrySet()) {
        getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
            .put(KeyStroke.getKeyStroke(mapping.getKey()), mapping.getKey());
        getRootPane().getActionMap().put(mapping.getKey(),
            new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    handleButtonClick(mapping.getValue());
                }
            });
    }
}

  这个键盘绑定功能真的让我费了不少心思!特别是要处理各种按键组合,还要考虑不同操作系统的差异。但是实现之后,用户体验真的提升了一个档次!⭐

🎵 音效反馈

  为了让计算器更有趣,我还加了点击音效:

private void playClickSound() {
    try {
        // 播放系统提示音
        Toolkit.getDefaultToolkit().beep();
    } catch (Exception e) {
        // 如果播放失败就算了,不影响主要功能
        System.out.println("音效播放失败,但不影响使用 😊");
    }
}

  虽然只是个简单的beep音,但确实能让操作更有反馈感!

🧠 表达式解析:让计算器更智能

📝 简单表达式解析

  基本的计算器只能一步一步算,但如果能支持表达式输入就更棒了!比如直接输入"2+3*4"这样的表达式:

public class ExpressionParser {
    
    public double evaluate(String expression) {
        // 去除空格
        expression = expression.replaceAll("\\s+", "");
        
        // 替换中文运算符
        expression = expression.replace("×", "*").replace("÷", "/");
        
        try {
            return evaluateExpression(expression);
        } catch (Exception e) {
            throw new IllegalArgumentException("表达式格式错误:" + expression);
        }
    }
    
    private double evaluateExpression(String expr) {
        // 这里实现一个简单的递归下降解析器
        return parseAdditionSubtraction(expr, new ParsePosition(0));
    }
    
    private double parseAdditionSubtraction(String expr, ParsePosition pos) {
        double result = parseMultiplicationDivision(expr, pos);
        
        while (pos.index < expr.length()) {
            char operator = expr.charAt(pos.index);
            if (operator == '+' || operator == '-') {
                pos.index++;
                double operand = parseMultiplicationDivision(expr, pos);
                result = (operator == '+') ? result + operand : result - operand;
            } else {
                break;
            }
        }
        
        return result;
    }
    
    // ... 其他解析方法
}

  这个表达式解析器虽然不复杂,但实现起来真的需要仔细考虑各种情况。特别是优先级处理,我可是参考了编译原理的知识!📚

🔍 错误处理

  表达式解析最容易出错的地方就是用户输入不规范。所以错误处理特别重要:

private void validateExpression(String expression) {
    // 检查括号是否匹配
    int parenthesesCount = 0;
    for (char c : expression.toCharArray()) {
        if (c == '(') parenthesesCount++;
        if (c == ')') parenthesesCount--;
        if (parenthesesCount < 0) {
            throw new IllegalArgumentException("括号不匹配!请检查表达式");
        }
    }
    
    if (parenthesesCount != 0) {
        throw new IllegalArgumentException("括号不匹配!请检查表达式");
    }
    
    // 检查是否有连续的运算符
    if (expression.matches(".*[+\\-*/]{2,}.*")) {
        throw new IllegalArgumentException("不能有连续的运算符!");
    }
    
    // 检查是否以运算符结尾
    if (expression.matches(".*[+\\-*/]$")) {
        throw new IllegalArgumentException("表达式不能以运算符结尾!");
    }
}

  这些验证规则看似简单,但都是我在实际使用中总结出来的。用户的输入千奇百怪,不做充分的验证,程序分分钟崩给你看!😅

🧹 清空与重置功能

🆑 多种清空模式

  一个好用的计算器,清空功能一定要做得细致:

public enum ClearMode {
    CLEAR_ENTRY,    // 清除当前输入
    CLEAR_ALL,      // 全部清除
    CLEAR_HISTORY   // 清除历史记录
}

private void performClear(ClearMode mode) {
    switch (mode) {
        case CLEAR_ENTRY:
            // 只清除当前显示的数字
            display.setText("0");
            break;
            
        case CLEAR_ALL:
            // 清除所有状态
            display.setText("0");
            firstOperand = 0;
            secondOperand = 0;
            currentOperator = "";
            isNewCalculation = true;
            operatorPressed = false;
            calculationHistory.clear();
            break;
            
        case CLEAR_HISTORY:
            // 只清除历史记录
            calculationHistory.clear();
            updateHistoryDisplay();
            break;
    }
    
    // 播放清除音效
    playClickSound();
}

  不同的清空模式满足不同的使用需求,这种细致的功能设计,真的能让用户感受到便利!

📜 历史记录功能

  我还给计算器加了历史记录功能,这个功能真的很实用:

private List<String> calculationHistory = new ArrayList<>();
private JTextArea historyArea;

private void addToHistory(String calculation, double result) {
    String historyEntry = String.format("%s = %.2f", calculation, result);
    calculationHistory.add(historyEntry);
    
    // 限制历史记录数量,避免内存占用过多
    if (calculationHistory.size() > 50) {
        calculationHistory.remove(0);
    }
    
    updateHistoryDisplay();
}

private void updateHistoryDisplay() {
    if (historyArea != null) {
        StringBuilder sb = new StringBuilder();
        for (int i = calculationHistory.size() - 1; i >= 0; i--) {
            sb.append(calculationHistory.get(i)).append("\n");
        }
        historyArea.setText(sb.toString());
    }
}

  历史记录按倒序显示,最新的计算结果在最上面,符合用户的使用习惯!

🎯 功能扩展:让计算器更强大

🔬 科学计算功能

  基本的四则运算满足不了我的野心,我还想加点科学计算功能:

private void addScientificFunctions() {
    String[] scientificFunctions = {
        "sin", "cos", "tan", "ln", "log", "√", "x²", "xⁿ", "π", "e"
    };
    
    JPanel scientificPanel = new JPanel(new GridLayout(2, 5, 5, 5));
    
    for (String function : scientificFunctions) {
        JButton button = createStyledButton(function, 
            new Color(100, 149, 237), Color.WHITE);
        button.addActionListener(e -> handleScientificFunction(function));
        scientificPanel.add(button);
    }
    
    // 添加到主界面
    add(scientificPanel, BorderLayout.SOUTH);
}

private void handleScientificFunction(String function) {
    double currentValue = Double.parseDouble(display.getText());
    double result = 0;
    
    switch (function) {
        case "sin":
            result = Math.sin(Math.toRadians(currentValue));
            break;
        case "cos":
            result = Math.cos(Math.toRadians(currentValue));
            break;
        case "tan":
            result = Math.tan(Math.toRadians(currentValue));
            break;
        case "ln":
            result = Math.log(currentValue);
            break;
        case "log":
            result = Math.log10(currentValue);
            break;
        case "√":
            result = Math.sqrt(currentValue);
            break;
        case "x²":
            result = currentValue * currentValue;
            break;
        case "π":
            result = Math.PI;
            break;
        case "e":
            result = Math.E;
            break;
    }
    
    display.setText(formatResult(result));
    addToHistory(function + "(" + currentValue + ")", result);
}

  有了这些科学计算功能,这个计算器瞬间就高大上了!数学课上再也不怕复杂运算了!📐

转存失败,建议直接上传图片文件

### 🎨 主题切换功能

  为了让界面更个性化,我还加了主题切换功能:

public enum Theme {
    LIGHT("浅色主题", new Color(240, 240, 240), Color.BLACK),
    DARK("深色主题", new Color(45, 45, 45), Color.WHITE),
    BLUE("蓝色主题", new Color(70, 130, 180), Color.WHITE),
    GREEN("绿色主题", new Color(60, 179, 113), Color.WHITE);
    
    private final String name;
    private final Color backgroundColor;
    private final Color textColor;
    
    Theme(String name, Color backgroundColor, Color textColor) {
        this.name = name;
        this.backgroundColor = backgroundColor;
        this.textColor = textColor;
    }
    
    // getters...
}

private void applyTheme(Theme theme) {
    // 更新显示屏颜色
    display.setBackground(theme.getBackgroundColor());
    display.setForeground(theme.getTextColor());
    
    // 更新按钮颜色
    for (JButton button : buttons.values()) {
        button.setBackground(theme.getBackgroundColor().brighter());
        button.setForeground(theme.getTextColor());
    }
    
    // 更新面板颜色
    getContentPane().setBackground(theme.getBackgroundColor());
    buttonPanel.setBackground(theme.getBackgroundColor());
    
    repaint();
}

  有了主题切换,用户可以根据自己的喜好选择界面风格,个性化程度瞬间拉满!🌈

比如我切换到蓝色主题,展示如下:

比如我再切换到紫色主题,展示如下:

🚧 开发过程中的踩坑经历

😅 布局管理器的坑

  说到踩坑,布局管理器绝对是Swing新手的噩梦!我当时为了让界面看起来更美观,尝试了各种布局管理器的组合:

// 这是我的第一版代码,看起来就很业余 😅
private void setupLayoutV1() {
    setLayout(new BorderLayout());
    
    // 顶部放显示屏
    add(display, BorderLayout.NORTH);
    
    // 中间放按钮,但是!!!按钮大小不一致!
    JPanel buttonPanel = new JPanel();
    // 没有设置布局管理器,默认是FlowLayout
    // 结果按钮排列乱七八糟...
    
    for (String text : buttonTexts) {
        buttonPanel.add(new JButton(text));
    }
    
    add(buttonPanel, BorderLayout.CENTER);
}

  结果界面惨不忍睹!按钮大小不一,排列混乱,简直不忍直视。后来我才明白,GridLayout才是计算器界面的最佳选择!

🐛 事件处理的bug

  还有一个让我头疼了好久的bug,就是连续点击运算符的处理:

// 有问题的代码
private void handleOperatorInputV1(String operator) {
    // 没有判断是否已经按过运算符
    if (!currentOperator.isEmpty()) {
        calculateResult();
    }
    
    currentOperator = operator;
    // 缺少状态标记,导致连续点击运算符时计算错误
}

  这个bug让我调试了整整一个下午!用户连续点击"+"号,结果计算结果完全错误。后来加了operatorPressed标记才解决:

// 修复后的代码
private void handleOperatorInput(String operator) {
    if (!operatorPressed) {  // 只有在没按过运算符时才计算
        if (!currentOperator.isEmpty()) {
            calculateResult();
        } else {
            firstOperand = Double.parseDouble(display.getText());
        }
    }
    
    currentOperator = operator;
    operatorPressed = true;  // 关键的状态标记!
    isNewCalculation = false;
}

💥 浮点数精度问题

  最坑的是浮点数精度问题!你知道0.1 + 0.2在计算机里不等于0.3吗?

System.out.println(0.1 + 0.2);  // 输出:0.30000000000000004

  为了解决这个问题,我专门写了一个格式化方法:

private String formatResult(double result) {
    // 使用BigDecimal处理精度问题
    BigDecimal bd = new BigDecimal(result);
    bd = bd.setScale(10, RoundingMode.HALF_UP);
    
    // 去除末尾的零
    String formatted = bd.stripTrailingZeros().toPlainString();
    
    // 如果结果太长,使用科学计数法
    if (formatted.length() > 12) {
        return String.format("%.6E", result);
    }
    
    return formatted;
}

  这个方法既保证了精度,又让显示结果更美观!

🚀 性能优化与用户体验

⚡ 响应速度优化

  虽然计算器功能相对简单,但响应速度还是很重要的:

// 使用SwingUtilities.invokeLater确保UI更新在EDT中执行
private void updateDisplay(String text) {
    SwingUtilities.invokeLater(() -> {
        display.setText(text);
        display.repaint();
    });
}

// 复杂计算使用后台线程
private void performComplexCalculation(String expression) {
    SwingWorker<Double, Void> worker = new SwingWorker<Double, Void>() {
        @Override
        protected Double doInBackground() throws Exception {
            return expressionParser.evaluate(expression);
        }
        
        @Override
        protected void done() {
            try {
                double result = get();
                updateDisplay(formatResult(result));
            } catch (Exception e) {
                updateDisplay("计算错误");
            }
        }
    };
    
    worker.execute();
}

🎨 界面美化技巧

  默认的Swing界面确实比较朴素,但通过一些技巧可以让它变得很漂亮:

private void beautifyInterface() {
    // 设置抗锯齿
    System.setProperty("awt.useSystemAAFontSettings", "on");
    System.setProperty("swing.aatext", "true");
    
    // 使用系统外观
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel());
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    // 自定义按钮样式
    UIManager.put("Button.font", new Font("Arial", Font.BOLD, 14));
    UIManager.put("Button.background", new Color(230, 230, 230));
    UIManager.put("Button.foreground", new Color(50, 50, 50));
}

💾 数据持久化

  为了让用户体验更好,我还加了配置保存功能:

private void saveSettings() {
    Properties props = new Properties();
    props.setProperty("theme", currentTheme.name());
    props.setProperty("window.x", String.valueOf(getX()));
    props.setProperty("window.y", String.valueOf(getY()));
    props.setProperty("scientific.mode", String.valueOf(scientificMode));
    
    try (FileOutputStream out = new FileOutputStream("calculator.properties")) {
        props.store(out, "Calculator Settings");
    } catch (IOException e) {
        System.err.println("保存设置失败:" + e.getMessage());
    }
}

private void loadSettings() {
    Properties props = new Properties();
    try (FileInputStream in = new FileInputStream("calculator.properties")) {
        props.load(in);
        
        String themeName = props.getProperty("theme", "LIGHT");
        currentTheme = Theme.valueOf(themeName);
        applyTheme(currentTheme);
        
        int x = Integer.parseInt(props.getProperty("window.x", "100"));
        int y = Integer.parseInt(props.getProperty("window.y", "100"));
        setLocation(x, y);
        
        scientificMode = Boolean.parseBoolean(props.getProperty("scientific.mode", "false"));
        
    } catch (Exception e) {
        // 如果加载失败,使用默认设置
        System.out.println("使用默认设置");
    }
}

📱 移动端适配思考

  虽然这个项目是桌面应用,但我也思考过移动端适配的问题:

// 响应式布局的尝试
private void adjustLayoutForScreenSize() {
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    
    if (screenSize.width < 800) {
        // 小屏幕设备,调整按钮大小和字体
        adjustForSmallScreen();
    } else if (screenSize.width > 1920) {
        // 大屏幕设备,可以显示更多功能
        adjustForLargeScreen();
    }
}

private void adjustForSmallScreen() {
    // 减小按钮尺寸,调整字体大小
    for (JButton button : buttons.values()) {
        button.setFont(new Font("Arial", Font.BOLD, 12));
        button.setPreferredSize(new Dimension(40, 40));
    }
    
    display.setFont(new Font("Monospaced", Font.BOLD, 18));
}

  虽然Swing在移动端的表现有限,但这种响应式的思维还是很重要的!

🎓 项目总结与心得感悟

💡 技术收获

  完成这个计算器项目后,我的收获真的很大:

1. Swing开发技能

  • 深入理解了各种布局管理器的特点和适用场景
  • 掌握了事件处理机制和监听器模式
  • 学会了组件自定义和界面美化技巧

2. 软件设计思维

  • 学会了从用户角度思考问题
  • 理解了状态管理在GUI应用中的重要性
  • 掌握了错误处理和异常管理的最佳实践

3. 代码质量意识

  • 重视代码的可读性和可维护性
  • 学会了合理的注释和文档编写
  • 养成了持续重构和优化的习惯

🚀 项目价值

  这个项目虽然功能相对简单,但它的价值远不止于此:

学习价值:通过实际项目练习GUI编程,比单纯看书效果好太多! 实用价值:日常使用中确实比系统自带的计算器好用! 展示价值:作为作品集的一部分,展示编程能力和UI设计感!

😊 个人感悟

  做这个项目最大的感悟就是:细节决定成败!一个好的软件,不仅要功能正确,更要在用户体验上下功夫。从界面美观到操作便捷,从错误处理到性能优化,每一个细节都关系到用户的使用感受。

  另外,持续优化也很重要。这个计算器我前前后后改了好多版本,每次都有新的想法和改进。软件开发就是这样一个不断完善的过程!

🔮 未来展望

  对于这个计算器项目,我还有很多想法没有实现:

  1. 更强大的表达式解析:支持更复杂的数学表达式
  2. 图形化显示:添加函数图像绘制功能
  3. 网络功能:支持在线汇率转换等
  4. 插件系统:允许用户自定义功能扩展
  5. 多平台发布:打包成可执行文件,方便分发

  技术永远在发展,我们的学习之路也永无止境!💪

🎉 结语:代码改变生活,创意点亮未来

  写到这里,我真的感慨万千!从最初的一个简单想法,到最终的成熟产品,这个Java计算器项目真的让我学到了太多东西。不仅仅是技术层面的提升,更重要的是对软件开发的理解和热爱!

  回想起刚开始写这个项目时的青涩和困惑,再看看现在相对成熟的代码和设计,真的有种"士别三日,当刮目相看"的感觉!每一次的调试、每一次的重构、每一次的优化,都是成长的印记。

  特别想感谢的是,这个项目让我深刻体会到了用户体验的重要性。写代码不只是让功能跑起来那么简单,更要考虑用户怎么使用、会遇到什么问题、如何让操作更便捷。这种"以用户为中心"的思维,不仅适用于软件开发,在生活的各个方面都很有价值!

  如果你也想尝试GUI编程,我强烈建议从一个小项目开始,比如这个计算器。不要害怕踩坑,不要担心代码不够优雅,重要的是动手去做!在实践中学习,在错误中成长,这就是程序员的修炼之路!🚀

  最后,希望我的这些经验分享能对大家有所帮助。如果你在开发过程中遇到什么问题,或者有什么好的想法和建议,非常欢迎交流讨论!让我们一起在代码的世界里探索更多可能性!

  编程改变世界,创意点亮未来!让我们继续在这条充满挑战和乐趣的道路上前行吧!✨

📣 关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主&最具价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-