Converting JDialog into Jframe/JPanel

2.2k views Asked by At

So I have this following code to make a quiz program. The code i'm using extends JDialog. I was wondering if there's a way to convert it to JPanel since when i try to run the code the window is all small and i can't seem to move the finished button next to the "Next" button. Also If i want to make the question be random how would one do that?

Thank You

import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import java.util.Random;
import javax.swing.JRadioButton;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class MultipleChoice extends JDialog {  
int correctAns;
List<Question> questions = new ArrayList<Question>();
//asnwers
JRadioButton[] responses;
ButtonGroup group = new ButtonGroup();
//bottom
JButton next = new JButton("Next");
JButton finish = new JButton("Finish");

public MultipleChoice(){
   super();
   setModal(true);
   setLayout( new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));  //setting up boxlayout
   
   questions.add(new Question("Which of the following is NOT one of the 5 great lakes?",new String[]{"Lake Mead","Lake Huron","Lake Michigan","Lake Erie"}, "Lake Mead"));
   questions.add(new Question("What is the Capital of Colorado?",new String[]{"Boulder","Aspen","Denver","Cheyenne"},"Denver"));
   questions.add(new Question("Each side of a baseball diamond is 90 feet in length. How far is it around the Baseball Diamond?",new String[]{"270","360","180","390"},"360"));
   questions.add(new Question("What color do you get when you combine an equal amount of red paint with an equal amount of yellow paint?",new String[]{"Blue","Orange","Green","Pink"},"Orange"));
   questions.add(new Question("How many sides does a trapezoid have?",new String[]{"3","4","5","6"},"2"));
   questions.add(new Question("Which is a simile?",new String[]{"My sister is cute like a bunny","My mom has a manly snore","My dad is better than yours"},"My sister is cute like a bunny"));
   questions.add(new Question("Polar bears eat penquins?",new String[]{"True","False"},"True"));

  //bottom
  next.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent ae){
          setVisible(false);
        }
    });
  finish.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent ae){
          setVisible(false);
        }
    });
   }

 public int beginQuiz(){  
        int score=0;
        for (Question q : questions){
            displayQuestion(q);
            if (group.getSelection().getActionCommand().equals(q.getans())){
                score++;
            }
        }
        dispose();
        return score;
 }
    
 private void displayQuestion(Question q){
        getContentPane().removeAll();
        for (Enumeration buttonGroup=group.getElements(); buttonGroup.hasMoreElements(); ){
            group.remove((AbstractButton)buttonGroup.nextElement());
        }
        
        JLabel questionText = new JLabel(q.getquestion());
        getContentPane().add(questionText);
        for (String answer : q.getanswers()){
            JRadioButton radio = new JRadioButton(answer);
            radio.setActionCommand(answer);
            group.add(radio);
            getContentPane().add(radio);
        }
        getContentPane().add(next);
        getContentPane().add(finish);
        pack();
        setVisible(true);
    }
    
public static void showSummary(int score){
  JOptionPane.showMessageDialog(null,"All Done :), here are your results"+
        "\nNumber of incorrect Answers: \t"+(7-score)+
        "\nNumber of Correct Answers: \t"+(score)+
        "\nPercent Correct: \t\t"+(int)(((float)(score)/7)*100)+"%"
    );
  if (((int)(((float)(score)/7)*100))> 0.6)
         JOptionPane.showMessageDialog(null,"You Passed!");
  else {
         JOptionPane.showMessageDialog(null,"You are NOT Smarter than a 5th Grader");
       }
}

 public static void main(String[] args){
  MultipleChoice quiz = new MultipleChoice();
  int score = quiz.beginQuiz();
  showSummary(score);
 }  
}

class Question {
private String question;
private String[] answers;
private String ans;

String getquestion(){    //getter
  return question;
 }
void setquestion(String str){    //setter
   question = str;
 }
 String[] getanswers(){    //getter
  return answers;
 }
 void setanswers(String[] str2){    //setter
   answers = str2;
 }
String getans(){    //getter
  return ans;
}
void setans(String str3){    //setter
   ans = str3;
 }

public Question(String possibleQuestion ,String[] possibleAnswer , String correctAnswer){     //constructor
   question = possibleQuestion;
   answers = possibleAnswer;
   ans = correctAnswer;
 }
 } 

Updated with new edits

After i edited and tried to convert it into JPanel and using cardlayout like suggested I ran into a few error and can't seem to figure out how to get the String[] possibleanswer and string correctanswer to display for the system to know and match the correct answer. here are my updated code

Thank You

import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import java.util.Random;
import java.awt.CardLayout;
import javax.swing.JRadioButton;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class MultipleChoice {  
int correctAns;
List<Question> questions = new ArrayList<Question>();
JPanel p=new JPanel();
CardLayout cards=new CardLayout();
int numQs;
int wrongs=0;
int total=0;

public static void main(String[] args){
  new MultipleChoice();
}  

public MultipleChoice(){
  JFrame frame = new JFrame("Are you Smarter than a 5th Grader?");
  frame.setResizable(true);
  frame.setSize(500,400);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
   questions.add(new Question("Which of the following is NOT one of the 5 great lakes?",new String[]{"Lake Mead","Lake Huron","Lake Michigan","Lake Erie"}, "Lake Mead"));
   questions.add(new Question("What is the Capital of Colorado?",new String[]{"Boulder","Aspen","Denver","Cheyenne"},"Denver"));
   questions.add(new Question("Each side of a baseball diamond is 90 feet in length. How far is it around the Baseball Diamond?",new String[]{"270","360","180","390"},"360"));
   questions.add(new Question("What color do you get when you combine an equal amount of red paint with an equal amount of yellow paint?",new String[]{"Blue","Orange","Green","Pink"},"Orange"));
   questions.add(new Question("How many sides does a trapezoid have?",new String[]{"3","4","5","6"},"2"));
   questions.add(new Question("Which is a simile?",new String[]{"My sister is cute like a bunny","My mom has a manly snore","My dad is better than yours"},"My sister is cute like a bunny"));
   questions.add(new Question("Polar bears eat penquins?",new String[]{"True","False"},"True"));
   
    p.setLayout(cards);
    numQs=questions.size();
    for(int i=0;i<numQs;i++){
        p.add(questions[i],"q"+i);
    }
    Random r=new Random();
    int i=r.nextInt(numQs);
    cards.show(p,"q"+i);
    frame.add(p);
    frame.setVisible(true);
 }

 public void next(){
    if((total-wrongs)==numQs){
        showSummary();
    }else{
        Random r=new Random();
        boolean found=false;
        int i=0;
        while(!found){
            i=r.nextInt(numQs);
            if(!questions[i].used){
                found=true;
            }
        }
        cards.show(p,"q"+i);
    }
}
    
 public void showSummary(){
  JOptionPane.showMessageDialog(null,"All Done :), here are your results"+
        "\nNumber of incorrect Answers: \t"+wrongs+
        "\nNumber of Correct Answers: \t"+(total-wrongs)+
        "\nPercent Correct: \t\t"+(int)(((float)(total-wrongs)/total)*100)+"%"
    );
  if (((int)(((float)(total-wrongs)/total)*100))> 0.6)
         JOptionPane.showMessageDialog(null,"You Passed!");
  else {
         JOptionPane.showMessageDialog(null,"You are NOT Smarter than a 5th Grader");
       }
    System.exit(0);
   }      
 }

class Question extends JPanel {
int correctAns;
MultipleChoice Choices; 
int selected;
boolean used;
//questions
JPanel qPanel=new JPanel();
//answers
JPanel aPanel=new JPanel();
JRadioButton[] responses;
//bottom
JPanel botPanel=new JPanel();
JButton next=new JButton("Next");
JButton finish=new JButton("Finish");

private String question;
private String[] answers;
private String ans;
public Question(String possibleQuestion ,String[] possibleAnswer , String correctAnswer){     //constructor
   this.Choices=Choices;
   question = possibleQuestion;
   answers = possibleAnswer;
   ans = correctAnswer;
   
   setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
    //question
   qPanel.add(new JLabel(question));
   add(qPanel);
    //answer
  responses=new JRadioButton[answers.length];
     //display possible answer and answers
  aPanel.add(responses[i]);
  
  add(aPanel);
  
  
    //bottom
    next.addActionListener(this);
    finish.addActionListener(this);
    botPanel.add(next);
    botPanel.add(finish);
    add(botPanel);
}

public Question(String possibleQuestion ,String[] possibleAnswer){   //constructor overloading
   question = possibleQuestion;
   answers = possibleAnswer;
}

String getquestion(){    //getter
  return question;
}
void setquestion(String str){    //setter
   question = str;
}
 String[] getanswers(){    //getter
  return answers;
 }
void setanswers(String[] str2){    //setter
   answers = str2;
}
 String getans(){    //getter
  return ans;
}
void setans(String str3){    //setter
   ans = str3;
}

public void actionPerformed(ActionEvent e){
    Object src=e.getSource();
    //next button
    if(src.equals(next)){
        if(selected==correctAns){
            used=true;
            Choices.next();
        }
    }
    //finish button
    if(src.equals(finish)){
        Choices.showSummary();
    }
  }
}

New Revisions So after I create the interface and implement it. I somehow can't seem to display the question or options. the JButton doens't seems to work.

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class MultipleChoice {  
JPanel p=new JPanel();
CardLayout cards=new CardLayout();
int numQs;
int wrongs=0;
int total=0;

public static void main(String[] args){
  new MultipleChoice();
}  

public MultipleChoice(){
  List<Question> questions = new ArrayList<>();
  
   questions.add(new Question("Which of the following is NOT one of the 5 great lakes?",new String[]{"Lake Mead","Lake Huron","Lake Michigan","Lake Erie"}, "Lake Mead"));
   questions.add(new Question("What is the Capital of Colorado?",new String[]{"Boulder","Aspen","Denver","Cheyenne"},"Denver"));
   questions.add(new Question("Each side of a baseball diamond is 90 feet in length. How far is it around the Baseball Diamond?",new String[]{"270","360","180","390"},"360"));
   questions.add(new Question("What color do you get when you combine an equal amount of red paint with an equal amount of yellow paint?",new String[]{"Blue","Orange","Green","Pink"},"Orange"));
   questions.add(new Question("How many sides does a trapezoid have?",new String[]{"3","4","5","6"},"2"));
   questions.add(new Question("Which is a simile?",new String[]{"My sister is cute like a bunny","My mom has a manly snore","My dad is better than yours"},"My sister is cute like a bunny"));
   questions.add(new Question("Polar bears eat penquins?",new String[]{"True","False"},"True"));
   
  JFrame frame = new JFrame("Are you Smarter than a 5th Grader?");
  frame.setResizable(true);
  frame.setSize(500,400);
  frame.add(new QuizPane(questions));
  frame.pack();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);

  }
 public class QuizPane extends JPanel {
    private CardLayout cardLayout;
    private int currentQuestion;
    private JButton next;
    private List<Question> question;

    private JPanel panelOfQuestions;
  public QuizPane(List<Question> question) {
        this.question = question;
        cardLayout = new CardLayout();
        panelOfQuestions = new JPanel(cardLayout);

        JButton start = new JButton("Start");
        start.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                currentQuestion = -1;
                next();
            }
        });

        JPanel filler = new JPanel(new GridBagLayout());
        filler.add(start);
        panelOfQuestions.add(filler, "start");

        for (int index = 0; index < question.size(); index++) {
            QuestionInterface quiz = question.get(index);
            QuestionPane pane = new QuestionPane(quiz);
            panelOfQuestions.add(pane, Integer.toString(index));
        }
        panelOfQuestions.add(new JLabel("The quiz is over"), "last");
        currentQuestion = 0;
        cardLayout.show(panelOfQuestions, "start");
      
        setLayout(new BorderLayout());
        add(panelOfQuestions);
        
        JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        next = new JButton("Next");
        buttonPane.add(next);
        next.setEnabled(false);

        add(buttonPane, BorderLayout.SOUTH);

        next.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                next();
            }
        }); 
    }
    public void next(){
      if (currentQuestion >= question.size()) {
            cardLayout.show(panelOfQuestions, "last");
            next.setEnabled(false);
            // You could could loop through all the questions and tally
            // the correct answers here
          } 
      else {
            cardLayout.show(panelOfQuestions, Integer.toString(currentQuestion));
            next.setText("Next");
            next.setEnabled(true);
        }
   }
    
   /*public void showSummary(){   // try to get to show summary after the quiz
    JOptionPane.showMessageDialog(null,"All Done :), here are your results"+
        "\nNumber of incorrect Answers: \t"+wrongs+
        "\nNumber of Correct Answers: \t"+(total-wrongs)+
        "\nPercent Correct: \t\t"+(int)(((float)(total-wrongs)/total)*100)+"%"
    );
    if (((int)(((float)(total-wrongs)/total)*100))> 0.6)
         JOptionPane.showMessageDialog(null,"You Passed!");
    else {
         JOptionPane.showMessageDialog(null,"You are NOT Smarter than a 5th Grader");
       }
    System.exit(0);
    }*/  
  
  }

  public interface QuestionInterface {

    public String getquestion();

    public String[] getOptions();

    public String getAnswer();

    public String getUserResponse();
    
    public void setUserResponse(String response);

    public boolean isCorrect();
  }
  public class Question implements QuestionInterface {
 private String possibleQuestion;
 private String[] Options;
 public String correctAnswer;
 
 private String userResponse;
 
 public Question(String possibleQuestion ,String[] Options , String correctAnswer){     //constructor
   this.possibleQuestion = possibleQuestion;
   this.Options = Options;
   this.correctAnswer = correctAnswer;
 }

 public Question(String possibleQuestion ,String[] possibleAnswer){   //constructor overloading
   this.possibleQuestion = possibleQuestion;
   this.Options = Options;
  }

 public String getquestion(){    //getter
  return possibleQuestion;
  }
  
 void setquestion(String str){    //setter
   possibleQuestion = str;
  }
  
 public String[] getOptions(){    //getter
   return Options;
 }
 
 void setanswers(String[] str2){    //setter
   Options = str2;
 }
 
 public String getAnswer(){    //getter
    return correctAnswer;
 }
 
 void setans(String str3){    //setter
   correctAnswer = str3;
 }
 
 public String getUserResponse() {
        return userResponse;
    }
    
 public void setUserResponse(String response) {
        userResponse = response;
    }
    
 public boolean isCorrect() {
        return getAnswer().equals(getUserResponse());
    }
}
 public class QuestionPane extends JPanel {

    private QuestionInterface question;

    public QuestionPane(QuestionInterface question) {
        this.question = question;

        setLayout(new BorderLayout());

        JLabel prompt = new JLabel("<html><b>" + question.getquestion() + "</b></html>");
        prompt.setHorizontalAlignment(JLabel.LEFT);

        add(prompt, BorderLayout.NORTH);

        JPanel guesses = new JPanel(new GridBagLayout());
        guesses.setBorder(new EmptyBorder(5, 5, 5, 5));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        gbc.anchor = GridBagConstraints.WEST;
       
        List<String> options = new ArrayList<>(Arrays.asList(question.getOptions()));
        options.add(question.getAnswer());
        Collections.sort(options);

        ButtonGroup bg = new ButtonGroup();
        for (String option : options) {
            JRadioButton btn = new JRadioButton(option);
            bg.add(btn);

            guesses.add(btn, gbc);
        }

        add(guesses);

    }

    public QuestionInterface getQuestion() {
        return question;
    }

    public class ActionHandler implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            getQuestion().setUserResponse(e.getActionCommand());
        }

        }

    }
 }
1

There are 1 answers

15
MadProgrammer On

The code i'm using extends JDialog. I was wondering if there's a way to convert it to JPanel

Welcome to the wonderful world of why you shouldn't extend from top level containers (or at least one of the reasons)

Start by extending MultipleChoice from a JPanel instead of a JDialog. This will produce a number of compiler errors...

  • setModal(true); Kind of pointless on a panel, so you can get rid of it
  • getContentPane(), well, a panel doesn't have a JRootPane so it doesn't have a content pane. You can use this instead
  • dispose. Well, a panel isn't a window, so it can't be "disposed" per se. I would personally replace this with some kind of Observer Pattern, which would provide notifications when the state of the quiz has changed (like the it has been completed) so that the caller can deal with it in the way they want to. The point is, don't make assumptions about how people might like to use your component
  • pack, well, this goes in the same boat as the others, so you can just get rid of it.
  • setVisible, well, Swing components are visible by default, so it's probably a bit pointless.

Know, all you need to do is create an instance of your MultipleChoice panel and add it to what ever container you want.

since when i try to run the code the window is all small and i can't seem to move the finished button next to the "Next" button

This is a layout issue. In your case, I would use compound layout, maybe using a FlowLayout for the buttons and a BorderLayout for the "questions" and button panel (in the SOUTH position).

Incidentally, you should probably be using a CardLayout to show the questions, which I presented in this surprisingly similar question.

Also If i want to make the question be random how would one do that?

Collections.shuffle(questions); is probably the easiest solution I can think of. Once you call it, the List will be randomly shuffled.

so i just edit the code i was wondering if you can gave some comments how to fix it. thank you

Well, there goes the context of the original answer...

  • Take a look at Collections Trail, you're using a List as if it was an array, that's now how they work.
  • Question (JPanel) doesn't implement ActionListener so next.addActionListener(this); isn't going to work
  • You forgot to wrap aPanel.add(responses[i]); in a loop and create the JRadioButtons, which all should be added to the same ButtonGroup
  • Choices in is Question never assigned a value and will generate a NullPointerException. I'd be worried about exposing MultipleChoice directly and would personally use a interface which provided the contract of what could be executed against the class
  • When adding your "possible" answers, you need to include your correct answer as well. I'd add build a List of JRadioButton, one for each possible answer and one for the correct answer, I would the use Collection.shuffle to shuffle this List in some random way and then add the buttons to the Question panel