Search code examples
javaswingjbuttonbuttongroup

Java - using a IsSelected function in radioButtons and JPanel


I have to set a "quiz" in Java, using JPanel and JRadioButton.

My code starts with reading a text from a file and putting it on a panel, with radio buttons, button groups and panel. So far, so good.

However my problem starts when I have to collect the data from the user and compare it with the right answers.

I have class Questions, Answers and Read (besides main and display on panel).

My way of thinking was that when the user clicks the submit button the code stars to check to quiz. However, nothing happens when I click it on the window opened.

I collect the data to ArrayList for comparison.

The checkQuiz method is supposed to be called after the user submits the quiz. It compares the radio button selected text with an answer. The program is supposed to be "running" until the user clicks the "submit" button, however I believe it does not happen.

I tried to use ActionListener in the code but I couldn't compare the user's choice with the data I am using.

I am sorry for the lots of code. I tried to post a mcve question. As far as I know the code is compilable, but I couldn't neglect any more lines.

Thank you for your help, and the code is below. App

Class DisplayOnPanel creates a Frame for the subclass to use:

import javax.swing.JFrame;

public class DisplayOnPanel extends JFrame {
    JFrame frame = new JFrame();
    public DisplayOnPanel(){
        frame.setSize(500,500);
    }
}

Class Main:

public class Main {
public static void main (String[]args){
      new Read();
    }
}

Clsas Questions:

public class Question {
private String _question;
private String _option1;
private String _option2;
private String _option3;
private String _option4;
private int _qIndex=0;
public Question(String question, String option1, String option2, String option3,
                String option4){
    this._question = question;
    this._option1 = option1;
    this._option2 = option2;
    this._option3 = option3;
    this._option4 = option4;


}
public void set_qIndex(int index) {
    this._qIndex = index;
}

Class Read - Reads from a file and then displays the results on the panel. It also fills ArrayLists with Answers, Questions, ButtonGroups and JPanels.

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Read extends DisplayOnPanel {


protected ArrayList<Question> Questions = new ArrayList<>();
protected ArrayList<ButtonGroup> BG = new ArrayList<>();
protected ArrayList<JPanel> JP = new ArrayList<>();
protected ArrayList<Answer> Answers = new ArrayList<>();
protected int qNumber = 0, finalscore = 0;
private JLabel lblScore;
private JToggleButton Submit = new JToggleButton();
//constructor

public Read() {
    super();
    //a "label" in the file will indicate the final score
    final int NUMBER_OF_LABELS_ADDED_TO_FRAME = 1;
    int number_of_lines_in_the_file, final_score = 0;
    try {
        number_of_lines_in_the_file = read(Questions);
        addButtonsToFrame(Questions, number_of_lines_in_the_file +
                NUMBER_OF_LABELS_ADDED_TO_FRAME, BG, JP);
        Submit.setText("Submit Quiz"); //create a submit button
        JPanel SubmitPanel = new JPanel();
        SubmitPanel.setVisible(true);
        this.add(SubmitPanel);
        SubmitPanel.add(Submit);

Submit.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    for (int i = 0; i < BG.size(); i++) {
                        //handle cases of the user didn't complete the test
                        if (BG.get(i).getSelection()==null) {
                            JOptionPane.showMessageDialog(frame, "Exam not finished - Restart.");
                            i=BG.size()-1; //finish the loop
                            frame.setVisible(false);
                            dispose();
                            new Read();
                        }
                    }
                    checkQuiz(BG, Answers, ONE_QUESTION_GRADE); //check quiz
                    Submit.setEnabled(false); //can't redo quiz //
                    // unless "Restart" pressed


                }
            });            
//adding final score label
        lblScore = new JLabel("Your Final Score: " + finalscore);
        add(lblScore);
        pack();
        this.setVisible(true);
        while (!Submit.isSelected()) {
            if (Submit.isSelected()) {
                checkQuiz(BG, Answers);
            }
        }
    } catch (FileNotFoundException e) {
        System.out.println("couldn't open file");
    }
}
//the method reads from the file


//returns the number of lines (quesiton) in the file

public int read(ArrayList<Question> Questions) throws FileNotFoundException {
    int number_of_lines = 0;
    try {
        File f = new File("C:\\Users\\Assaf\\Desktop\\exam.txt");
        Scanner input = new Scanner(f);
        //read from file direcly into the constructor
        while (input.hasNext()) {
            Question q = new Question((input.nextLine())
                    , (input.nextLine()),
                    (input.nextLine()),
                    (input.nextLine()),
                    (input.nextLine()));
            //adding the question and the answers to an array
            Questions.add(q);
            number_of_lines++;
            q.set_qIndex(number_of_lines);
            Answers.add(new Answer(q));

        }
        input.close();
    } catch (FileNotFoundException nf) {
        System.out.println("couldn't open file");
    }
    //return number of lines in the file
    return number_of_lines;
}
public void addButtonsToFrame(ArrayList<Question> q, int number_of_lines,
                              ArrayList<ButtonGroup> BG, ArrayList<JPanel> JP) {
    int j = 0;
    for (int i = 0; i < q.size(); i++) {
        qNumber = i;
        BG.add(new ButtonGroup());
        JP.add(new JPanel());
        JP.get(i).setSize(499, 400);
        //creating buttons
JRadioButton option1 = new JRadioButton(q.get(i).get_option1());
option1.setActionCommand(q.get(i).get_option1());
JRadioButton option2 = new JRadioButton(q.get(i).get_option2());
option2.setActionCommand(q.get(i).get_option2());
JRadioButton option3 = new JRadioButton(q.get(i).get_option3());
option3.setActionCommand(q.get(i).get_option3());
JRadioButton option4 = new JRadioButton(q.get(i).get_option4());
option4.setActionCommand(q.get(i).get_option4());
        //adding to group buttons
        BG.get(j).add(option1);
        BG.get(j).add(option2);
        BG.get(j).add(option3);
        BG.get(j).add(option4);
        //adding the buttons to the panel
        JP.get(j).add(option1);
        JP.get(j).add(option2);
        JP.get(j).add(option3);
        JP.get(j).add(option4);
        //setting layout that matches our goal
        this.setLayout(new GridLayout(number_of_lines + 1, 1));
        //set title and border for each question
        JP.get(i).setBorder(BorderFactory.createTitledBorder(
                BorderFactory.createEtchedBorder(), "question number " + qNumber + ": " + q.get(i).get_question()));
        //adding the panel to the frame
        this.add(JP.get(j));
        //BG.get(i).getSelection()
        JP.get(j).setVisible(true);
        j++;
    }
}
public void checkQuiz(ArrayList<ButtonGroup> BG, ArrayList<Answer> A) {
    ArrayList<String> Selections = new ArrayList<>();
    int CORRECT_ANSWER = 0;
    for (int i = 0; i < BG.size(); i++) {
        if (BG.get(i).getSelection().getActionCommand()
                .compareTo(A.get(i).get_answer()) == CORRECT_ANSWER) {
            finalscore = finalscore + 10;
        }
    }

}

Class Answer

public class Answer {
private String _question;
private String _answer;
private int _qIndex=0;

public Answer (Question q){
    this._answer = q.get_option1();
    this._question=q.get_question();
    this._qIndex=q.get_qIndex();

}

Edit - posted my working code.


Solution

  • i) You need to set action command before getting it,

    JRadioButton option1 = new JRadioButton(q.get(i).get_option1());
    option1.setActionCommand(q.get(i).get_option1());
    JRadioButton option2 = new JRadioButton(q.get(i).get_option2());
    option2.setActionCommand(q.get(i).get_option2());
    JRadioButton option3 = new JRadioButton(q.get(i).get_option3());
    option3.setActionCommand(q.get(i).get_option3());
    JRadioButton option4 = new JRadioButton(q.get(i).get_option4());
    option4.setActionCommand(q.get(i).get_option4());
    

    ii) You haven't set the final score in your label in the end of checkQuiz method,
    lblScore.setText("Your Final Score: " + finalscore);

    iii) It is not advisable to use a while loop. Also checkQuiz method will not be invoked most of the time with the current logic you use. Hence use an ActionListener interface instead of a while,

    Submit.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
             checkQuiz(BG, Answers);
        }
    });