import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
public class MathPractice extends JFrame implements ActionListener {
// 界面组件
JLabel titleLab, questionLab, tipLab, scoreLab;
JTextField ansInput;
JButton submitBtn, nextBtn;
JComboBox<String> levelBox;
// 业务变量
Random random = new Random();
int score = 0; // 得分
double num1, num2; // 两个操作数
char op; // 运算符
int level; // 难度 1简单 2中等 3困难
// 构造方法:初始化窗口
public MathPractice() {
initWindow();
initComponent();
createQuestion(); // 初始生成第一道题
}
// 窗口基础设置
private void initWindow() {
setTitle("小学生算术练习器");
setSize(450, 320);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // 窗口居中
setLayout(null); // 绝对布局,方便新手
setResizable(false);
}
// 初始化所有控件
private void initComponent() {
// 标题
titleLab = new JLabel("算术练习题", SwingConstants.CENTER);
titleLab.setFont(new Font("黑体", Font.BOLD, 24));
titleLab.setBounds(80, 20, 300, 35);
add(titleLab);
// 难度下拉框
JLabel levelLab = new JLabel("选择难度:");
levelLab.setBounds(60, 70, 80, 25);
add(levelLab);
String[] levels = {"简单(整数10以内)", "中等(整数100以内)", "困难(小数)"};
levelBox = new JComboBox<>(levels);
levelBox.setBounds(140, 70, 200, 25);
add(levelBox);
// 题目显示
questionLab = new JLabel("题目:", SwingConstants.CENTER);
questionLab.setFont(new Font("宋体", Font.BOLD, 20));
questionLab.setBounds(50, 110, 350, 30);
add(questionLab);
// 答案输入框
ansInput = new JTextField();
ansInput.setBounds(100, 150, 120, 30);
ansInput.setFont(new Font("宋体", Font.PLAIN, 18));
add(ansInput);
// 提交、下一题按钮
submitBtn = new JButton("提交答案");
submitBtn.setBounds(240, 150, 90, 30);
submitBtn.addActionListener(this);
add(submitBtn);
nextBtn = new JButton("换一题");
nextBtn.setBounds(140, 190, 130, 30);
nextBtn.addActionListener(this);
add(nextBtn);
// 对错提示
tipLab = new JLabel("请输入答案", SwingConstants.CENTER);
tipLab.setBounds(50, 230, 350, 25);
add(tipLab);
// 得分
scoreLab = new JLabel("当前得分:0");
scoreLab.setBounds(160, 260, 120, 25);
add(scoreLab);
}
// 生成随机算式
private void createQuestion() {
tipLab.setText("请输入答案");
ansInput.setText("");
// 获取选中难度
level = levelBox.getSelectedIndex() + 1;
// 随机运算符 + - * /
char[] ops = {'+', '-', '*', '/'};
op = ops[random.nextInt(4)];
if (level == 1) {
// 简单:1~10整数
num1 = random.nextInt(10) + 1;
num2 = random.nextInt(10) + 1;
} else if (level == 2) {
// 中等:1~100整数
num1 = random.nextInt(100) + 1;
num2 = random.nextInt(100) + 1;
} else {
// 困难:1~50小数,保留1位小数
num1 = Math.round((1 + random.nextDouble() * 49) * 10.0) / 10.0;
num2 = Math.round((1 + random.nextDouble() * 49) * 10.0) / 10.0;
}
// 除法避免除0
while (op == '/' && num2 == 0) {
if (level <= 2) num2 = random.nextInt(100)+1;
else num2 = Math.round((1 + random.nextDouble() * 49) * 10.0) / 10.0;
}
questionLab.setText(num1 + " " + op + " " + num2 + " = ?");
}
@Override
public void actionPerformed(ActionEvent e) {
// 换一题按钮
if (e.getSource() == nextBtn) {
createQuestion();
return;
}
// 提交答案按钮
if (e.getSource() == submitBtn) {
String inputStr = ansInput.getText().trim();
if (inputStr.isEmpty()) {
tipLab.setText("提示:请输入数字!");
tipLab.setForeground(Color.RED);
return;
}
double userAns;
try {
userAns = Double.parseDouble(inputStr);
} catch (Exception ex) {
tipLab.setText("输入格式错误,请输入数字!");
tipLab.setForeground(Color.RED);
return;
}
// 计算标准答案
double realAns = switch (op) {
case '+' -> num1 + num2;
case '-' -> num1 - num2;
case '*' -> num1 * num2;
case '/' -> num1 / num2;
default -> 0;
};
// 允许微小误差(小数精度问题)
if (Math.abs(userAns - realAns) < 0.01) {
tipLab.setText("回答正确!+10分");
tipLab.setForeground(new Color(0, 150, 0));
score += 10;
} else {
tipLab.setText("回答错误,正确答案:" + String.format("%.2f", realAns));
tipLab.setForeground(Color.RED);
}
scoreLab.setText("当前得分:" + score);
}
}
public static void main(String[] args) {
// Swing程序建议在UI线程启动
SwingUtilities.invokeLater(() -> {
new MathPractice().setVisible(true);
});
}
}

Java Swing 图形界面实验心得体会
本次实验围绕 Java Swing 开发小学生算术练习软件展开,系统学习了 GUI 图形界面编程与事件处理机制,从搭建窗口、布局组件到实现随机出题、答案校验、难度切换等完整功能,收获颇丰,也发现了自身存在的不少问题。在前期知识点学习阶段,我明白了 Swing 各类组件(JFrame、JLabel、JButton、JTextField、下拉框 JComboBox)的作用,理清了 GUI 编程核心逻辑:界面组件搭建、事件源绑定、事件监听器处理三者配合运行。之前只写过纯控制台程序,初次接触可视化界面时,对窗口大小、坐标布局、字体样式调整较为陌生,通过不断调整控件位置、修改字体颜色,慢慢熟悉了可视化界面的设计思路,也意识到美观、简洁的界面能大幅提升软件使用体验。
实验核心难点是事件处理机制。所有按钮点击、下拉框切换功能都依靠 ActionListener 监听实现,最开始分不清事件源、监听接口、重写方法三者的关系,多次出现点击按钮无响应的问题。排查后发现是忘记为控件绑定监听器,或是判断点击对象时逻辑写错。通过分步调试,我掌握了统一实现 ActionListener 接口、重写 actionPerformed 方法来区分不同按钮业务逻辑的写法,理解了图形程序是依靠用户操作触发代码执行,而非控制台顺序执行的运行逻辑。
随机出题功能的实现让我巩固了随机数、分支判断、浮点运算等基础语法。区分简单、中等、困难三种难度,分别生成整数、小数四则运算,还要处理除法除数不能为 0、小数精度误差等细节问题。最初没有考虑浮点数计算精度,出现答案正确却判定错误的 bug,后来通过差值对比允许微小误差才解决问题,让我懂得开发程序不能只实现基础功能,还要预判边界异常场景,做好容错处理,比如输入非数字时给出提示、输入为空拦截提交。同时本次实验也锻炼了代码分层思想,我将窗口初始化、控件创建、生成题目、事件处理拆分为独立方法,代码结构清晰,便于修改和扩展。实验要求可拓展分数运算、错题记录、计时功能,也让我意识到软件开发具备很强的可扩展性,后续可以基于现有框架新增功能,不用大面积重构代码。对比选做的终端扫雷游戏需求,也分清了控制台程序与 Swing 图形程序开发思路的差异,图形界面交互更直观,但组件、事件逻辑更复杂。在实操过程中,我也暴露了不少不足:一是界面布局不够熟练,使用绝对坐标布局不够灵活,后期可以学习流式布局、网格布局优化界面;二是异常处理意识薄弱,一开始没有对输入内容做校验,容易造成程序崩溃;三是代码复用性不足,重复代码较多。后续我会多练习布局管理器,养成输入校验、异常捕获的编码习惯,多用方法封装重复逻辑。整体而言,这次实验打通了 Java 图形化开发的完整流程,不再只会枯燥的控制台代码,学会将代码转化为可视化交互软件,深刻理解了面向对象思想在 GUI 中的应用,同时培养了调试排错、需求拆解、功能拓展的工程思维,为后续学习桌面程序、图形交互开发打下了扎实基础。