|
|
package com.mathlearning.view;
|
|
|
|
|
|
import com.mathlearning.controller.QuestionController;
|
|
|
import com.mathlearning.model.Question;
|
|
|
import javax.swing.*;
|
|
|
import java.awt.*;
|
|
|
import java.awt.event.ActionEvent;
|
|
|
import java.awt.event.ActionListener;
|
|
|
import java.util.List;
|
|
|
|
|
|
public class QuizFrame extends JFrame {
|
|
|
private QuestionController questionController;
|
|
|
private String level;
|
|
|
private int totalQuestions;
|
|
|
private LevelSelectionFrame parentFrame;
|
|
|
private JLabel questionNumberLabel;
|
|
|
private JLabel questionTextLabel;
|
|
|
private JRadioButton[] optionButtons;
|
|
|
private ButtonGroup buttonGroup;
|
|
|
private JButton previousButton;
|
|
|
private JButton nextButton;
|
|
|
private JProgressBar progressBar;
|
|
|
|
|
|
// 存储所有题目和用户选择
|
|
|
private List<Question> allQuestions;
|
|
|
private int[] userSelections;
|
|
|
private int currentDisplayIndex; // 当前显示的题目索引
|
|
|
|
|
|
public QuizFrame(String level, int questionCount, LevelSelectionFrame parent) {
|
|
|
this.parentFrame = parent;
|
|
|
this.level = level;
|
|
|
this.totalQuestions = questionCount;
|
|
|
this.questionController = new QuestionController();
|
|
|
this.questionController.startNewQuiz(level, questionCount);
|
|
|
|
|
|
// 获取所有题目
|
|
|
this.allQuestions = questionController.getCurrentQuestions();
|
|
|
this.userSelections = new int[questionCount];
|
|
|
this.currentDisplayIndex = 0;
|
|
|
|
|
|
// 初始化选择为-1(未选择)
|
|
|
for (int i = 0; i < userSelections.length; i++) {
|
|
|
userSelections[i] = -1;
|
|
|
}
|
|
|
|
|
|
initializeUI();
|
|
|
showCurrentQuestion();
|
|
|
}
|
|
|
|
|
|
private void initializeUI() {
|
|
|
setTitle("数学答题 - " + level);
|
|
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
setSize(700, 550);
|
|
|
setLocationRelativeTo(null);
|
|
|
setResizable(false);
|
|
|
|
|
|
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
|
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
|
|
|
|
|
// 顶部面板(退出按钮和进度条)
|
|
|
JPanel topPanel = new JPanel(new BorderLayout());
|
|
|
|
|
|
JButton exitButton = new JButton("退出答题");
|
|
|
exitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
|
|
exitButton.setBackground(new Color(220, 100, 100));
|
|
|
exitButton.setForeground(Color.WHITE);
|
|
|
exitButton.addActionListener(e -> exitQuiz());
|
|
|
|
|
|
progressBar = new JProgressBar(0, totalQuestions);
|
|
|
progressBar.setValue(0);
|
|
|
progressBar.setStringPainted(true);
|
|
|
progressBar.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
|
|
|
|
|
topPanel.add(exitButton, BorderLayout.WEST);
|
|
|
topPanel.add(progressBar, BorderLayout.CENTER);
|
|
|
mainPanel.add(topPanel, BorderLayout.NORTH);
|
|
|
|
|
|
// 问题面板
|
|
|
JPanel questionPanel = new JPanel(new BorderLayout(10, 20));
|
|
|
questionPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
|
|
|
|
|
questionNumberLabel = new JLabel("", JLabel.CENTER);
|
|
|
questionNumberLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
|
|
|
questionNumberLabel.setForeground(new Color(0, 100, 200));
|
|
|
questionPanel.add(questionNumberLabel, BorderLayout.NORTH);
|
|
|
|
|
|
questionTextLabel = new JLabel("", JLabel.CENTER);
|
|
|
questionTextLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 20));
|
|
|
questionTextLabel.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10));
|
|
|
questionPanel.add(questionTextLabel, BorderLayout.CENTER);
|
|
|
|
|
|
mainPanel.add(questionPanel, BorderLayout.CENTER);
|
|
|
|
|
|
// 选项面板
|
|
|
JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 10, 10));
|
|
|
optionsPanel.setBorder(
|
|
|
BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY), "请选择答案"));
|
|
|
|
|
|
optionButtons = new JRadioButton[4];
|
|
|
buttonGroup = new ButtonGroup();
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
optionButtons[i] = new JRadioButton();
|
|
|
optionButtons[i].setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
|
|
|
optionButtons[i].setBackground(Color.WHITE);
|
|
|
optionButtons[i].setFocusPainted(false);
|
|
|
optionButtons[i].setPreferredSize(new Dimension(400, 40));
|
|
|
|
|
|
final int index = i;
|
|
|
optionButtons[i].addActionListener(
|
|
|
e -> {
|
|
|
// 保存当前选择
|
|
|
userSelections[currentDisplayIndex] = index;
|
|
|
System.out.println("用户选择: 第" + (currentDisplayIndex + 1) + "题 -> 选项" + index);
|
|
|
});
|
|
|
|
|
|
buttonGroup.add(optionButtons[i]);
|
|
|
optionsPanel.add(optionButtons[i]);
|
|
|
}
|
|
|
|
|
|
JPanel optionsContainer = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
|
|
optionsContainer.add(optionsPanel);
|
|
|
|
|
|
// 控制面板
|
|
|
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
|
|
|
|
|
|
previousButton = new JButton("上一题");
|
|
|
previousButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
|
|
|
previousButton.setBackground(new Color(169, 169, 169));
|
|
|
previousButton.setForeground(Color.WHITE);
|
|
|
previousButton.setFocusPainted(false);
|
|
|
previousButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
|
|
|
previousButton.setEnabled(false); // 第一题时禁用
|
|
|
|
|
|
nextButton = new JButton("下一题");
|
|
|
nextButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
|
|
|
nextButton.setBackground(new Color(70, 130, 180));
|
|
|
nextButton.setForeground(Color.WHITE);
|
|
|
nextButton.setFocusPainted(false);
|
|
|
nextButton.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
|
|
|
|
|
|
controlPanel.add(previousButton);
|
|
|
controlPanel.add(nextButton);
|
|
|
|
|
|
JPanel southPanel = new JPanel(new BorderLayout());
|
|
|
southPanel.add(optionsContainer, BorderLayout.CENTER);
|
|
|
southPanel.add(controlPanel, BorderLayout.SOUTH);
|
|
|
mainPanel.add(southPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
// 添加事件监听器
|
|
|
previousButton.addActionListener(new PreviousQuestionAction());
|
|
|
nextButton.addActionListener(new NextQuestionAction());
|
|
|
|
|
|
add(mainPanel);
|
|
|
}
|
|
|
|
|
|
private void showCurrentQuestion() {
|
|
|
if (currentDisplayIndex >= allQuestions.size()) {
|
|
|
finishQuiz();
|
|
|
return;
|
|
|
}
|
|
|
Question currentQuestion = allQuestions.get(currentDisplayIndex);
|
|
|
questionNumberLabel.setText(
|
|
|
String.format("第 %d 题 / 共 %d 题", currentDisplayIndex + 1, totalQuestions));
|
|
|
questionTextLabel.setText(
|
|
|
"<html><div style='text-align: center;'>"
|
|
|
+ currentQuestion.getQuestionText()
|
|
|
+ "</div></html>");
|
|
|
String[] options = currentQuestion.getOptions();
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
String optionText =
|
|
|
String.format(
|
|
|
"<html><div style='padding: 5px;'>%c. %s</div></html>", (char) ('A' + i), options[i]);
|
|
|
optionButtons[i].setText(optionText);
|
|
|
}
|
|
|
buttonGroup.clearSelection(); // 清除当前选择状态
|
|
|
// 恢复之前的选择(如果有)
|
|
|
if (userSelections[currentDisplayIndex] != -1) {
|
|
|
int previousSelection = userSelections[currentDisplayIndex];
|
|
|
if (previousSelection >= 0 && previousSelection < 4) {
|
|
|
optionButtons[previousSelection].setSelected(true);
|
|
|
}
|
|
|
}
|
|
|
// 更新进度条
|
|
|
progressBar.setValue(currentDisplayIndex);
|
|
|
progressBar.setString(
|
|
|
String.format(
|
|
|
"%d/%d (%.0f%%)",
|
|
|
currentDisplayIndex,
|
|
|
totalQuestions,
|
|
|
((double) currentDisplayIndex / totalQuestions) * 100));
|
|
|
updateButtonStates(); // 更新按钮状态
|
|
|
}
|
|
|
|
|
|
private void exitQuiz() {
|
|
|
int result =
|
|
|
JOptionPane.showConfirmDialog(this, "确定要退出答题吗?所有进度将丢失。", "退出确认", JOptionPane.YES_NO_OPTION);
|
|
|
if (result == JOptionPane.YES_OPTION) {
|
|
|
parentFrame.setVisible(true);
|
|
|
this.dispose();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void updateButtonStates() {
|
|
|
// 更新上一题按钮状态
|
|
|
previousButton.setEnabled(currentDisplayIndex > 0);
|
|
|
|
|
|
// 更新下一题按钮文本
|
|
|
if (currentDisplayIndex == totalQuestions - 1) {
|
|
|
nextButton.setText("完成答题");
|
|
|
} else {
|
|
|
nextButton.setText("下一题");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private class PreviousQuestionAction implements ActionListener {
|
|
|
@Override
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
if (currentDisplayIndex > 0) {
|
|
|
currentDisplayIndex--;
|
|
|
showCurrentQuestion();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private class NextQuestionAction implements ActionListener {
|
|
|
@Override
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
// 检查是否选择了答案
|
|
|
int selectedIndex = -1;
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
if (optionButtons[i].isSelected()) {
|
|
|
selectedIndex = i;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
userSelections[currentDisplayIndex] = selectedIndex; // 保存当前选择
|
|
|
// 如果没有选择答案,提示用户但允许继续(除了最后一题)
|
|
|
if (selectedIndex == -1) {
|
|
|
int result =
|
|
|
JOptionPane.showConfirmDialog(
|
|
|
QuizFrame.this, "您还没有选择答案,确定要继续下一题吗?", "确认", JOptionPane.YES_NO_OPTION);
|
|
|
if (result != JOptionPane.YES_OPTION) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
// 前进到下一题或完成
|
|
|
if (currentDisplayIndex < totalQuestions - 1) {
|
|
|
currentDisplayIndex++;
|
|
|
showCurrentQuestion();
|
|
|
} else {
|
|
|
submitAllAnswers(); // 完成所有题目,提交答案并显示分数
|
|
|
finishQuiz();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void submitAllAnswers() {
|
|
|
// 计算分数
|
|
|
int score = 0;
|
|
|
for (int i = 0; i < totalQuestions; i++) {
|
|
|
if (userSelections[i] != -1) {
|
|
|
// 使用 QuestionController 来检查答案
|
|
|
questionController.setCurrentQuestionIndex(i);
|
|
|
if (questionController.submitAnswer(userSelections[i])) {
|
|
|
score++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 重置到第一个问题,以便在结果显示时能正确访问
|
|
|
questionController.setCurrentQuestionIndex(0);
|
|
|
}
|
|
|
|
|
|
private void finishQuiz() {
|
|
|
// 使用原有的构造函数
|
|
|
ScoreFrame scoreFrame =
|
|
|
new ScoreFrame(questionController, userSelections, allQuestions, parentFrame);
|
|
|
scoreFrame.setVisible(true);
|
|
|
this.dispose();
|
|
|
}
|
|
|
} // 添加这个闭合大括号
|