关于java JCheckBox的位置问题请教
package ui;
import entity.Question;
import main.ExamSystem;
import service.QuestionService;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
public class ExamUI extends JFrame {
private JLabel labelQuestion;
private JRadioButton optionA;
private JRadioButton optionB;
private JRadioButton optionC;
private JRadioButton optionD;
// 修改位置:添加多选框
private JCheckBox multiOptionA;
private JCheckBox multiOptionB;
private JCheckBox multiOptionC;
private JCheckBox multiOptionD;
private ButtonGroup options;
private JButton buttonConfirm;
private JButton buttonNext;
private JButton buttonPrev;
private JButton buttonReset;
public Question currentQuestion;
private final Object lock = new Object();
// private ExamSystem examSystem;
private final ArrayList<Question> questions;
private int currentIndex=0;
private final long startTime;
private JPanel optionsPanel;
private JPanel mainPanel;
public ExamUI(long startTime) throws ClassNotFoundException {
super("题库练习");
this.startTime=startTime;
optionsPanel=new JPanel();
optionsPanel.setLayout(new BoxLayout(optionsPanel,BoxLayout.Y_AXIS));
setSize(750, 550);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
questions = (ArrayList<Question>) QuestionService.getQuestions();
init(); // Call init here to initialize components
if (!questions.isEmpty()){
showQuestion(questions.get(0));
}
setVisible(true); // Make sure to call setVisible(true) after initializing components
}
private void init() {
options = new ButtonGroup();
mainPanel = new JPanel(new BorderLayout()); // Use BorderLayout for mainPanel
labelQuestion = new JLabel("");
mainPanel.add(labelQuestion, BorderLayout.NORTH);
optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS));
optionA = new JRadioButton("选项 A");
optionB = new JRadioButton("选项 B");
optionC = new JRadioButton("选项 C");
optionD = new JRadioButton("选项 D");
//初始化多选框
multiOptionA = new JCheckBox("选项 A");
multiOptionB = new JCheckBox("选项 B");
multiOptionC = new JCheckBox("选项 C");
multiOptionD = new JCheckBox("选项 D");
Font optionFont = new Font("Dialog", Font.PLAIN, 20); // 创建一个新的字体对象
optionA.setFont(optionFont);
optionB.setFont(optionFont);
optionC.setFont(optionFont);
optionD.setFont(optionFont);
//设置多选框的字体
multiOptionA.setFont(optionFont);
multiOptionB.setFont(optionFont);
multiOptionC.setFont(optionFont);
multiOptionD.setFont(optionFont);
optionA.addItemListener(new ItemStateChange());
optionB.addItemListener(new ItemStateChange());
optionC.addItemListener(new ItemStateChange());
optionD.addItemListener(new ItemStateChange());
//为多选框添加监听器
multiOptionA.addItemListener(new ItemStateChange());
multiOptionB.addItemListener(new ItemStateChange());
multiOptionC.addItemListener(new ItemStateChange());
multiOptionD.addItemListener(new ItemStateChange());
options.add(optionA);
options.add(optionB);
options.add(optionC);
options.add(optionD);
// 修改位置:将多选框添加到选项面板
optionsPanel.add(Box.createVerticalStrut(25));
optionsPanel.add(optionA);
optionsPanel.add(Box.createVerticalStrut(55));
optionsPanel.add(optionB);
optionsPanel.add(Box.createVerticalStrut(55));
optionsPanel.add(optionC);
optionsPanel.add(Box.createVerticalStrut(55));
optionsPanel.add(optionD);
optionsPanel.add(multiOptionA);
optionsPanel.add(Box.createVerticalStrut(55));
optionsPanel.add(multiOptionB);
optionsPanel.add(Box.createVerticalStrut(55));
optionsPanel.add(multiOptionC);
optionsPanel.add(Box.createVerticalStrut(55));
optionsPanel.add(multiOptionD);
mainPanel.add(optionsPanel, BorderLayout.CENTER); // Add optionsPanel to the center of mainPanel
JPanel buttonsPanel = new JPanel(); // Panel for buttons
buttonConfirm = new JButton("确认");
buttonNext = new JButton("下一题");
buttonPrev = new JButton("上一题");
buttonReset = new JButton("重置");
JButton buttonScore = new JButton("评分");
JButton buttonExit = new JButton("退出");
buttonConfirm.addActionListener(e -> checkAnswer());
buttonsPanel.add(buttonConfirm);
buttonsPanel.add(buttonNext);
buttonsPanel.add(buttonPrev);
buttonsPanel.add(buttonReset);
buttonsPanel.add(buttonScore);
buttonsPanel.add(buttonExit);
mainPanel.add(buttonsPanel, BorderLayout.SOUTH); // Add buttonsPanel to the bottom of mainPanel
add(mainPanel); // Add mainPanel to the JFrame
buttonNext.addActionListener(e -> {
// 判断是否还有下一题
if (currentIndex < questions.size() - 1) {
currentIndex++;
// 显示下一题
showQuestion(questions.get(currentIndex));
} else {
JOptionPane.showMessageDialog(ExamUI.this, "已经是最后一题了!");
}
buttonConfirm.setEnabled(true);
if (currentIndex==questions.size()-1){
buttonConfirm.setEnabled(false);
}
});
buttonPrev.addActionListener(e -> {
// 判断是否还有上一题
if (currentIndex > 0) {
currentIndex--;
// 显示上一题
showQuestion(questions.get(currentIndex));
} else {
JOptionPane.showMessageDialog(ExamUI.this, "已经是第一题了!");
}
buttonConfirm.setEnabled(false);
});
buttonReset.addActionListener(e -> {
//切换回第一题
currentIndex=0;
showQuestion(questions.get(currentIndex));
//清除所有选择
options.clearSelection();
//重置所有统计信息
ExamSystem.correctCount = 0;
ExamSystem.incorrectCount = 0;
ExamSystem.totalCount = 0;
// 使所有选项按钮可用
optionA.setEnabled(true);
optionB.setEnabled(true);
optionC.setEnabled(true);
optionD.setEnabled(true);
// 重置所有问题的回答状态
for (Question question : questions) {
question.setAnswered(false);
question.setUserAnswer(null);
}
buttonReset.setEnabled(true); // 保持重置按钮可用
});
buttonScore.addActionListener(e -> {
if (currentIndex==questions.size()-1){
// Call the static method from ExamSystem to display statistics in the UI
ExamSystem.showStatistics(ExamUI.this);
// Disable other buttons if needed
buttonConfirm.setEnabled(false);
buttonNext.setEnabled(false);
buttonPrev.setEnabled(false);
buttonReset.setEnabled(true);
}else {
JOptionPane.showMessageDialog(ExamUI.this,"请在评分前完成所有题目");
}
});
buttonExit.addActionListener(e -> System.exit(0));
}
public void showStatistics(int correctCount, int incorrectCount, int totalCount) {
// 在UI中显示统计信息
long endTime=System.currentTimeMillis();
long useTime=(endTime-startTime)/1000;
double correctRate = (double) correctCount / totalCount * 100;
JOptionPane.showMessageDialog(this, "答题统计\n----------------\n答对题目:" + correctCount + "\n答错题目:" + incorrectCount + "\n总题目:" + totalCount + "\n正确率:" + correctRate + "%");
JOptionPane.showMessageDialog(this,"用时:"+useTime+"秒");
}
public void showQuestion(Question question) {
// Set the current question
this.currentQuestion = question;
// Set the question text
labelQuestion.setText(question.getTitle());
// Set the question text and increase the font size
labelQuestion.setText(question.getTitle());
labelQuestion.setFont(new Font(labelQuestion.getFont().getName(), Font.PLAIN, 20)); // 修改位置:设置字体大小为20
// Set the options text with prefixes
optionA.setText("A. " + question.getOptionA());
optionB.setText("B. " + question.getOptionB());
optionC.setText("C. " + question.getOptionC());
optionD.setText("D. " + question.getOptionD());
//修改位置:设置多选框的文本
multiOptionA.setText("A. " + question.getOptionA());
multiOptionB.setText("B. " + question.getOptionB());
multiOptionC.setText("C. " + question.getOptionC());
multiOptionD.setText("D. " + question.getOptionD());
boolean isJudgement=question.isJudgeQuestion();
boolean isMultipleChoice=question.isMultipleChoice(); // 修改位置:添加一个判断是否为多选题的变量
// 修改位置:根据题目类型显示对应的答案选项类型
if (isJudgement || !isMultipleChoice) {
optionA.setVisible(true);
optionB.setVisible(true);
optionC.setVisible(!isJudgement);
optionD.setVisible(!isJudgement);
multiOptionA.setVisible(false);
multiOptionB.setVisible(false);
multiOptionC.setVisible(false);
multiOptionD.setVisible(false);
} else{
optionA.setVisible(false);
optionB.setVisible(false);
optionC.setVisible(false);
optionD.setVisible(false);
multiOptionA.setVisible(true);
multiOptionB.setVisible(true);
multiOptionC.setVisible(true);
multiOptionD.setVisible(true);
}
// Clear any previous selection
options.clearSelection();
String userAnswer=question.getUserAnswer();
if (userAnswer!=null){
switch (userAnswer){
case "A":
optionA.setSelected(true);
break;
case "B":
optionB.setSelected(true);
break;
case "C":
if (!isJudgement) { /// 修改位置:只有当不是判断题时才会处理 C 的答案状态 ///
optionC.setSelected(true);
}
break;
case "D":
if (!isJudgement) { /// 修改位置:同上 ///
optionD.setSelected(true);
}
break;
}
}
boolean answered=question.isAnswered();
// 使所有选项按钮可用
optionA.setEnabled(!answered);
optionB.setEnabled(!answered);
optionC.setEnabled(!answered);
optionD.setEnabled(!answered);
// 修改位置:设置多选框的可用状态
multiOptionA.setEnabled(!answered);
multiOptionB.setEnabled(!answered);
multiOptionC.setEnabled(!answered);
multiOptionD.setEnabled(!answered);
// 如果问题已经回答并且回答正确,则确认按钮不可用
if (answered && QuestionService.validateAnswer(currentQuestion, userAnswer)) {
buttonConfirm.setEnabled(false);
} else if (answered) {
buttonConfirm.setEnabled(false);
}
// Repaint the frame to update the UI
validate();
repaint();
optionC.setText("C. "+question.getOptionC());
optionD.setText("D. "+question.getOptionD());
if (currentIndex==questions.size()-1){
buttonConfirm.setEnabled(false);
}
}
class ItemStateChange implements ItemListener {
public void itemStateChanged(ItemEvent e) {
// 当任何一个选项被选中时,如果当前问题还没有被回答,使确认按钮可用
if (!currentQuestion.isAnswered()) {
buttonConfirm.setEnabled(true);
}
}
}
public void checkAnswer() {
// 判断答案
String selectedOption=getSelectedOption();
currentQuestion.setUserAnswer(selectedOption);
currentQuestion.setAnswered(true);
// 保存当前问题的答案
String correctAnswer = currentQuestion.getAnswer();
if (QuestionService.validateAnswer(currentQuestion, getSelectedOption())) {
ExamSystem.correctCount++; // increment correctCount
//若回答正确,自动切换下一题
if (currentIndex < questions.size() - 1) {
currentIndex++;
// 显示下一题
showQuestion(questions.get(currentIndex));
// 设置新问题的回答状态为未回答
questions.get(currentIndex).setAnswered(false);
} else {
JOptionPane.showMessageDialog(this, "已经是最后一题了");
buttonConfirm.setEnabled(false);
}
} else {
ExamSystem.incorrectCount++; // increment incorrectCount
optionA.setEnabled(false);
optionB.setEnabled(false);
optionC.setEnabled(false);
optionD.setEnabled(false);
buttonConfirm.setEnabled(false);
}
// 显示用户答案和正确答案
JOptionPane.showMessageDialog(this, "您的答案是:" + selectedOption + "\n正确答案是:" + correctAnswer);
ExamSystem.totalCount++; // increment totalCount only once per question
buttonConfirm.setEnabled(false);
}
public String getSelectedOption() {
// 返回选中的选项
if (optionA.isSelected()) {
return "A";
} else if (optionB.isSelected()) {
return "B";
} else if (optionC.isSelected()) {
return "C";
} else if (optionD.isSelected()) {
return "D";
}
// 修改位置:如果是多选题,返回所有选中的选项
else if (currentQuestion.isMultipleChoice()) {
StringBuilder selectedOptions = new StringBuilder();
if (multiOptionA.isSelected()) {
selectedOptions.append("A");
}
if (multiOptionB.isSelected()) {
selectedOptions.append("B");
}
if (multiOptionC.isSelected()) {
selectedOptions.append("C");
}
if (multiOptionD.isSelected()) {
selectedOptions.append("D");
}
return selectedOptions.toString();
}
return null;
}
// 等待用户选择答案
public String waitForAnswer() {
synchronized(lock) {
try {
lock.wait();
} catch (InterruptedException ignored) {}
}
return getSelectedOption();
}
// 显示判断结果
public void showResult(boolean isCorrect) {
if(isCorrect) {
JOptionPane.showMessageDialog(this, "回答正确!");
} else {
JOptionPane.showMessageDialog(this, "回答错误!");
}
// 唤醒等待线程
synchronized(lock) {
lock.notify();
}
}
public static void main(String[] args) {
new WelcomeUI();
}
}
这是编写的简陋数据库连接进行题库模拟,包括单选题判断题和多选题,当到多选题时题目复选框位置突然跑了,特请指教,想让复选框位置
如何实现复选框位置和单选框位置相同