Java NetBeans GUI builder读取文本文件时如何等待用户事件后继续操作
问题根因
CLI是线性同步流程,用Scanner获取输入时会阻塞整个程序等待用户操作,等输入完成才继续走循环。但Swing是事件驱动模型,你写的for循环运行在Swing的事件调度线程中,循环过程中界面更新不会立刻渲染,会等整个方法执行完才统一刷新,因此你只会看到最后一道题的内容,相当于循环直接把15道题全刷完了。
解决方案
完全不需要硬编码题目,只要调整代码逻辑适配GUI的事件触发机制即可:
第一步:封装题目实体类
新建Question类统一存储单道题的所有信息,避免逐行读取的混乱:
public class Question { private String content; private String optionA; private String optionB; private String optionC; private String optionD; private String correctAnswer; public Question(String content, String a, String b, String c, String d, String answer) { this.content = content; this.optionA = a; this.optionB = b; this.optionC = c; this.optionD = d; this.correctAnswer = answer; } // 以下为Get方法 public String getContent() { return content; } public String getOptionA() { return optionA; } public String getOptionB() { return optionB; } public String getOptionC() { return optionC; } public String getOptionD() { return optionD; } public String getCorrectAnswer() { return correctAnswer; } }
第二步:改造InputOutput类,一次性读取所有题目到内存
不要每次点按钮才逐行读,游戏初始化时直接把所有题目读到List中,避免IO异常中途中断游戏:
public List<Question> loadAllQuestions() { List<Question> questionList = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader("./resources/Questions.txt"))) { String line; // 按你的文件格式,每6行对应一道题:题干、a、b、c、d、正确答案 while ((line = br.readLine()) != null) { String content = line; String a = br.readLine(); String b = br.readLine(); String c = br.readLine(); String d = br.readLine(); String answer = br.readLine(); questionList.add(new Question(content, a, b, c, d, answer)); } } catch (FileNotFoundException e) { System.out.println("题目文件未找到"); } catch (IOException e) { System.out.println("题目读取错误"); } return questionList; }
第三步:给界面类添加全局变量
存储当前答题进度和所有题目数据:
// 加在界面类的成员变量位置 private List<Question> questionList; // 当前题目索引,从0开始 private int currentQuestionIndex = 0; // 当前题的正确答案,用于校验用户输入 private String currentCorrectAnswer;
第四步:改写开始按钮逻辑,拆分题目加载方法
把原来的开始按钮点击事件改造成仅做初始化,单独抽离题目加载方法方便后续切题调用:
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) { // 游戏初始化,仅执行一次 InputOutput getIO = new InputOutput(); questionList = getIO.loadAllQuestions(); currentQuestionIndex = 0; // 加载第一道题 loadCurrentQuestion(); } // 单独抽离的题目加载方法,后续切题直接调用即可 private void loadCurrentQuestion() { // 15题答完或者所有题目读完,结束游戏 if (currentQuestionIndex >= questionList.size() || currentQuestionIndex >= 15) { JOptionPane.showMessageDialog(this, "所有题目作答完成!"); return; } Question currentQ = questionList.get(currentQuestionIndex); jTextField1.setText(currentQ.getContent()); jTextField2.setText(currentQ.getOptionA()); jTextField3.setText(currentQ.getOptionB()); jTextField4.setText(currentQ.getOptionC()); jTextField5.setText(currentQ.getOptionD()); currentCorrectAnswer = currentQ.getCorrectAnswer(); }
第五步:给提交答案按钮添加切题逻辑
用户选完答案点击提交后,再触发下一题加载:
// 你自己的提交答案按钮的点击事件 private void submitBtnMouseClicked(java.awt.event.MouseEvent evt) { // 此处添加你自己的答案校验逻辑,比如获取用户选择的选项和currentCorrectAnswer对比,判断正误计分 // 校验完成后索引+1,加载下一题 currentQuestionIndex++; loadCurrentQuestion(); }
注意事项
不要用Thread.sleep()或者死循环去卡主线程等待输入,会直接导致界面无响应卡死。Swing所有交互都靠事件触发,用户点击提交按钮的动作就是触发下一题的信号,不需要主动做等待逻辑。
内容的提问来源于stack exchange,提问作者Justformaddenpurposes
相关产品推荐
相关产品推荐

