用JFrame+GridLayout搭计算器最稳妥,因其布局可控、事件响应明确;GridLayout保证4×5按钮网格整齐对齐,代码量少且逻辑直白;需注意行数在前(5行)、列数在后(4列),显示屏用setEditable(false)的JTextField,按钮统一监听,用pack()自适应尺寸。

为什么直接用 JFrame + GridLayout 搭按钮最稳妥
Swing 做计算器,核心是布局可控、事件响应明确。用 BorderLayout 或绝对定位容易错位,尤其在窗口缩放或不同 DPI 下;GridLayout 能保证 4×5(含显示屏)按钮网格整齐对齐,且代码量最少、逻辑最直白。
实操建议:
- 用
new GridLayout(5, 4)创建面板,注意行数在前(5 行:显示屏 + 4 行按钮),列数在后(4 列) - 显示屏用
JTextField,设为setEditable(false),避免键盘误输 - 所有数字和运算符按钮统一用
addActionListener(this),在actionPerformed中用e.getActionCommand()区分操作 - 别忘了调用
pack()而非setSize(),让组件自适应尺寸
actionPerformed 里怎么安全处理连续点击和双符号
用户可能连点 +、输入 12+3+5 或误按 ==,硬编码判断容易漏 case。关键是把状态拆成三部分:当前输入值、上一个运算符、是否等待新数字。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
- 点两次
+后再输数字,结果变成0+数字(没保留上次计算中间值) - 点
=后继续输数字,没清空屏幕或重置状态,导致拼接错误表达式
推荐做法:
- 用三个字段:
private double lastValue(上次参与运算的数)、private String pendingOperator(待执行的运算符)、private boolean startNewNumber(标识下一次输入是否覆盖显示) - 遇到数字按钮时:若
startNewNumber为true,清空文本框并设为false;否则追加字符 - 遇到运算符按钮时:先尝试执行上一次未完成的计算(如果有
pendingOperator),再更新pendingOperator和lastValue -
=按钮只触发一次计算,之后设startNewNumber = true,允许输入新数字
为什么不用 Double.parseDouble() 直接转字符串表达式
初学者常想把整个屏幕字符串(如 "12+3*5")丢给 parseDouble,这会抛 NumberFormatException —— 它只能转纯数字字符串,不支持表达式求值。
正确路径只有两条:
- 简单计算器:只支持单步运算(如
12 + 3 =),每次只记一个操作符和两个操作数,用switch分支做四则运算 - 稍进阶:手写简易表达式解析器,用两个栈(数字栈、运算符栈),按优先级弹出计算(适合练手,但别在作业里硬套 Shunting Yard 算法)
千万别引入 javax.script.ScriptEngine——虽然能跑 "12+3*5",但它启动慢、有安全风险、Swing 主线程阻塞明显,且偏离“理解事件流与状态管理”的教学目标。
字体和监听器泄漏这两个细节最容易被忽略
计算器界面太小字看不清,但直接 setFont(new Font("Arial", 0, 18)) 在 Linux 或 macOS 上可能 fallback 成方块;另外,反复 addActionListener 却不 removeActionListener,会导致旧按钮仍响应事件(尤其在动态重建面板时)。
解决方式很具体:
- 用
UIManager.put("Label.font", new Font("Dialog", Font.PLAIN, 16))统一设置系统级默认字体,比逐个设更可靠 - 按钮初始化只做一次:在构造函数里创建按钮数组,循环添加监听器,不要在事件处理中重复
add - 如果真要动态刷新界面(比如切换主题),先用
button.removeActionListener(this)清理,再重建
真正卡住人的往往不是算法,而是 startNewNumber 没在该设 true 的时候设,或者字体在高分屏上缩成一条线——这些得运行起来点几遍才看得见。











