0

I want to create buttons within buttons in java gui, so I have a bunch of buttons and within those buttons there's more buttons but whenever I try to make a for-loop for those buttons nothing happens. Here is my code

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.ImageIcon;
import java.net.URL;
import java.awt.Dimension;
import javax.swing.JOptionPane;
import java.awt.*;
import javax.swing.ImageIcon;
import java.awt.Dimension;


public class Elements extends JPanel implements ActionListener {

  JButton c_one[] = new JButton[4];
  JButton c_two[] = new JButton[4];
  JButton c_three[] = new JButton[4];
  JButton c_four[] = new JButton[4];
  JButton THINGY [] = new JButton[1];

  // buttons for column one row 0
  JButton btn1 = new JButton("Nicosia");
  JButton btn2 = new JButton("Mumbai");
  JButton btn3 = new JButton("Dubait");
  JButton btn4 = new JButton("Romania");
  // buttons for column one row 1
  JButton btna = new JButton("semihemidemisemiquaver ");
  JButton btnb = new JButton("semidemiquaver");
  JButton btnc = new JButton("qaver");
  JButton btnd = new JButton("stop note");
  // button column one row 2
  JButton btne = new JButton("23 ");
  JButton btnf = new JButton("27");
  JButton btng = new JButton("72");
  JButton btnh = new JButton("4");
  // button colooum one row 3
  JButton btnE = new JButton("Pinky");
  JButton btnF = new JButton("Cotten Candy");
  JButton btnG = new JButton("Lady");
  JButton btnH = new JButton(" The Other Tide.");
  // button column two row 0
  JButton btn10 = new JButton("\tEverything about you");
  JButton btn20 = new JButton("All about the thing in the janitors closet");
  JButton btn30 = new JButton("If Dubait  is real or not");
  JButton btn40 = new JButton("12");
  // button column two row 1
  JButton btn00 = new JButton("$63,645, ");
  JButton btn01 = new JButton("$120 000");
  JButton btn02 = new JButton("$15");
  JButton btn03 = new JButton("$64 200");
  // button column two row 2
  JButton btn04 = new JButton("True ");
  JButton btn05 = new JButton("False");
  // button column two row 3
  JButton btnaa = new JButton("\tMr. Penny");
  JButton btnbb = new JButton("Mr. Dime");
  JButton btncc = new JButton("Mr. Nickel");
  JButton btndd = new JButton("Mr.Dollar");
  // button column three row 1
  JButton btn06 = new JButton("\tDr. Harold Shipman");
  JButton btn07 = new JButton("Jesse James.");
  JButton btn08 = new JButton("Pablo Escobar");
  JButton btn09 = new JButton("Al Capone");
  // button column three row 2
  JButton btnaaa = new JButton("\tTrue");
  JButton btnbbb = new JButton("False");
  JButton btnddd = new JButton("Only in the bladder");
  // button column three row 3
  JButton btnEE = new JButton("20% ");
  JButton btnFF = new JButton("6 to 9%,");
  JButton btnGG = new JButton("11-17%");
  JButton btnHH = new JButton("34%");
  // button column three row 4
  JButton question11 = new JButton("Does stretching delay muscle soreness");
  JButton btn12 = new JButton("Stretching before or after exercise does NOT reduce muscle soreness ");
  JButton btn13 = new JButton("Stretching before or after exercise DOES reduce soreness");

  // JPanel.setBackground(Color.YELLOW);
  int PE = 0;
  GridBagConstraints constraints = new GridBagConstraints(); // this variable will set the coordinates of each button
  String icon[] = { "ont.jpg", "oet.jpg", "cm.jpg","riddles.jpg","stw.jpg" };

  public Elements() {

    setLayout(new GridBagLayout());

    constraints.insets = new Insets(5, 5, 5, 5); // borders

    for (int k = 0; k < (c_one.length); k++) {
      c_one[k] = new JButton();
      constraints.gridx = 0;
      ++constraints.gridy;
      c_one[k].setIcon(
          new ImageIcon(new ImageIcon(icon[0]).getImage().getScaledInstance(150, 100, java.awt.Image.SCALE_SMOOTH)));
      add(c_one[k], constraints);
      c_one[k].addActionListener(this);
    }

    constraints.gridy = -1; // setting the gridy to be negative one so the loop will iterate starting at
                            // gridy = 0
    for (int j = 0; j < (c_two.length); j++) {
      c_two[j] = new JButton();
      constraints.gridx = 1;
      ++constraints.gridy;
      c_two[j].setIcon(
          new ImageIcon(new ImageIcon(icon[1]).getImage().getScaledInstance(150, 100, java.awt.Image.SCALE_SMOOTH)));
      add(c_two[j], constraints);
      c_two[j].addActionListener(this);
    }

    // gridy = 0;
    constraints.gridy = -1;

    for (int m = 0; m < (c_three.length); m++) {
      c_three[m] = new JButton();
      constraints.gridx = 2;
      ++constraints.gridy;
      c_three[m].setIcon(
          new ImageIcon(new ImageIcon(icon[2]).getImage().getScaledInstance(150, 100, java.awt.Image.SCALE_SMOOTH)));
      add(c_three[m], constraints);
      c_three[m].addActionListener(this);
    }
   constraints.gridy = -1; // setting the gridy to be negative one so the loop will iterate starting at
                            // gridy = 0
    for (int j = 0; j < (c_four.length); j++) {
   c_four[j] = new JButton();
      constraints.gridx = 3;
      ++constraints.gridy;
      c_four[j].setIcon(
          new ImageIcon(new ImageIcon(icon[3]).getImage().getScaledInstance(150, 100, java.awt.Image.SCALE_SMOOTH)));
      add(c_four[j], constraints);
      c_four[j].addActionListener(this);
    }
       constraints.gridy = -1; // setting the gridy to be negative one so the loop will iterate starting at
                            // gridy = 0
    for (int j = 0; j < (THINGY.length); j++) {
      THINGY[j] = new JButton();
      constraints.gridx = 6;
      ++constraints.gridy;
      THINGY[j].setIcon(
          new ImageIcon(new ImageIcon(icon[4]).getImage().getScaledInstance(150, 100, java.awt.Image.SCALE_SMOOTH)));
      add(THINGY[j], constraints);
      THINGY[j].addActionListener(this);
    }
    JButton pointsEarned = new JButton("Points Earned");
    constraints.fill = GridBagConstraints.VERTICAL;
    constraints.ipady = 20;
    constraints.gridx = 3;
    constraints.gridy = 0;
    constraints.anchor = GridBagConstraints.PAGE_START;
    add(pointsEarned, constraints);
  }

  @Override
  public void actionPerformed(ActionEvent e) {

    if (e.getSource() == c_one[0]) {
      System.out.println(" For 200 points. What is the capital of Cyprus?");
      JFrame frame = new JFrame("200");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question1 = new JButton("For 200 points. What is the capital of Cyprus?");
      question1.setBounds(50, 100, 160, 80);
      question1.setBackground(Color.ORANGE);
      panel.add(question1);
      btn2.setBounds(50, 100, 80, 30);
      btn2.setBackground(Color.ORANGE);
      btn1.setBounds(50, 100, 80, 30);
      btn1.setBackground(Color.ORANGE);
      panel.add(btn1);
      panel.add(btn2);
      btn3.setBounds(50, 100, 80, 30);
      btn3.setBackground(Color.ORANGE);
      panel.add(btn3);
      btn4.setBounds(50, 100, 80, 30);
      btn4.setBackground(Color.ORANGE);
      panel.add(btn4);
      frame.add(panel);
      frame.setSize(535, 250);
      frame.setLayout(null);
      frame.setVisible(true);

    } else if (e.getSource() == c_one[1]) {
      System.out
          .println("For 400 points. What is a note that is played for half the duration of a thirty second note?");
      JFrame frame2 = new JFrame("400");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question2 = new JButton("In music, a hundred twenty-eighth note is known as?");
      question2.setBounds(50, 100, 160, 80);
      question2.setBackground(Color.ORANGE);
      panel.add(question2);
      btna.setBounds(50, 100, 80, 30);
      btna.setBackground(Color.ORANGE);
      btnb.setBounds(50, 100, 80, 30);
      btnb.setBackground(Color.ORANGE);
      panel.add(btna);
      panel.add(btnb);
      btnc.setBounds(50, 100, 80, 30);
      btnc.setBackground(Color.ORANGE);
      panel.add(btnc);
      btnd.setBounds(50, 100, 80, 30);
      btnd.setBackground(Color.ORANGE);
      panel.add(btnd);
      frame2.add(panel);
      frame2.setSize(535, 250);
      frame2.setLayout(null);
      frame2.setVisible(true);
    }

    if (e.getSource() == c_one[2]) {
      JFrame frame3 = new JFrame("600");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question3 = new JButton("How many times was Caesar stabbed by his senators?");
      question3.setBounds(50, 100, 160, 80);
      question3.setBackground(Color.ORANGE);
      panel.add(question3);
      btne.setBounds(50, 100, 80, 30);
      btne.setBackground(Color.ORANGE);
      btnf.setBounds(50, 100, 80, 30);
      btnf.setBackground(Color.ORANGE);
      panel.add(btne);
      panel.add(btnf);
      btng.setBounds(50, 100, 80, 30);
      btng.setBackground(Color.ORANGE);
      panel.add(btng);
      btnh.setBounds(50, 100, 80, 30);
      btnh.setBackground(Color.ORANGE);
      panel.add(btnh);
      frame3.add(panel);
      frame3.setSize(535, 250);
      frame3.setLayout(null);
      frame3.setVisible(true);
    } else if (e.getSource() == c_one[3]) {
      JFrame frame4 = new JFrame("800");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question4 = new JButton("Louisiana is home to a rare pink dolphin named:");
      question4.setBounds(50, 100, 160, 100);
      question4.setBackground(Color.ORANGE);
      panel.add(question4);
      btnE.setBounds(50, 100, 80, 30);
      btnE.setBackground(Color.ORANGE);
      btnF.setBounds(50, 100, 80, 30);
      btnF.setBackground(Color.ORANGE);
      panel.add(btnE);
      panel.add(btnF);
      btnG.setBounds(50, 100, 80, 30);
      btnG.setBackground(Color.ORANGE);
      panel.add(btnG);
      btnH.setBounds(50, 100, 80, 30);
      btnH.setBackground(Color.ORANGE);
      panel.add(btnH);
      frame4.add(panel);
      frame4.setSize(535, 250);
      frame4.setLayout(null);
      frame4.setVisible(true);
    }
    // array 2
    if (e.getSource() == c_two[0]) {
      JFrame frame = new JFrame("200");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question1 = new JButton("What do teachers know?");
      question1.setBounds(50, 100, 160, 80);
      question1.setBackground(Color.ORANGE);
      panel.add(question1);
      btn10.setBounds(50, 100, 80, 30);
      btn10.setBackground(Color.ORANGE);
      btn20.setBounds(50, 100, 80, 30);
      btn20.setBackground(Color.ORANGE);
      panel.add(btn10);
      panel.add(btn20);
      btn30.setBounds(50, 100, 80, 30);
      btn30.setBackground(Color.ORANGE);
      panel.add(btn30);
      btn40.setBounds(50, 100, 80, 30);
      btn40.setBackground(Color.ORANGE);
      panel.add(btn40);
      frame.add(panel);
      frame.setSize(535, 250);
      frame.setLayout(null);
      frame.setVisible(true);
    } else if (e.getSource() == c_two[1]) {
      System.out.println("Who is my physics teacher");
      JFrame frame2 = new JFrame("400");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question2 = new JButton("Who is my physics teacher?");
      question2.setBounds(50, 100, 160, 80);
      question2.setBackground(Color.ORANGE);
      panel.add(question2);
      btnaa.setBounds(50, 100, 80, 30);
      btnaa.setBackground(Color.ORANGE);
      btnbb.setBounds(50, 100, 80, 30);
      btnbb.setBackground(Color.ORANGE);
      panel.add(btnaa);
      panel.add(btnbb);
      btncc.setBounds(50, 100, 80, 30);
      btncc.setBackground(Color.ORANGE);
      panel.add(btncc);
      btndd.setBounds(50, 100, 80, 30);
      btndd.setBackground(Color.ORANGE);
      panel.add(btndd);
      frame2.add(panel);
      frame2.setSize(535, 250);
      frame2.setLayout(null);
      frame2.setVisible(true);

    }
    if (e.getSource() == c_two[2]) {
      JFrame frame4 = new JFrame("600");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question4 = new JButton("How much do teachers get payed on average");
      question4.setBounds(50, 100, 160, 100);
      question4.setBackground(Color.ORANGE);
      panel.add(question4);
      btn00.setBounds(50, 100, 80, 30);
      btn00.setBackground(Color.ORANGE);
      btn01.setBounds(50, 100, 80, 30);
      btn01.setBackground(Color.ORANGE);
      panel.add(btn00);
      panel.add(btn01);
      btn02.setBounds(50, 100, 80, 30);
      btn02.setBackground(Color.ORANGE);
      panel.add(btn02);
      btn03.setBounds(50, 100, 80, 30);
      btn03.setBackground(Color.ORANGE);
      panel.add(btn03);
      frame4.add(panel);
      frame4.setSize(535, 250);
      frame4.setLayout(null);
      frame4.setVisible(true);

    } else if (e.getSource() == c_two[3]) {
      JFrame frame3 = new JFrame("800");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 600, 800);
      panel.setBackground(Color.BLUE);
      JButton question3 = new JButton("For every 10 Canadian teachers, at least 4 have endured violence from students");
      question3.setBounds(50, 100, 160, 180);
      question3.setBackground(Color.ORANGE);
      panel.add(question3);

      btn04.setBounds(50, 100, 80, 30);
      btn04.setBackground(Color.ORANGE);
      btn05.setBounds(50, 100, 80, 30);
      btn05.setBackground(Color.ORANGE);
      panel.add(btn04);
      panel.add(btn05);
      frame3.add(panel);
      frame3.setSize(800, 500);
      frame3.setLayout(null);
      frame3.setVisible(true);
    }
    // array 3
    if (e.getSource() == c_three[0]) {
      JFrame frame = new JFrame("200");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question1 = new JButton("The most prolific modern serial killer is:");
      question1.setBounds(50, 100, 160, 80);
      question1.setBackground(Color.ORANGE);
      panel.add(question1);
      btn06.setBounds(50, 100, 80, 30);
      btn06.setBackground(Color.ORANGE);
      btn07.setBounds(50, 100, 80, 30);
      btn07.setBackground(Color.ORANGE);
      panel.add(btn06);
      panel.add(btn07);
      btn08.setBounds(50, 100, 80, 30);
      btn08.setBackground(Color.ORANGE);
      panel.add(btn08);
      btn09.setBounds(50, 100, 80, 30);
      btn09.setBackground(Color.ORANGE);
      panel.add(btn09);
      frame.add(panel);
      frame.setSize(535, 250);
      frame.setLayout(null);
      frame.setVisible(true);
    } else if (e.getSource() == c_three[1]) {
      JFrame frame2 = new JFrame("400");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question2 = new JButton("Urine is sterile\t");
      question2.setBounds(50, 100, 160, 80);
      question2.setBackground(Color.ORANGE);
      panel.add(question2);
      btnaaa.setBounds(50, 100, 80, 30);
      btnaaa.setBackground(Color.ORANGE);
      btnbbb.setBounds(50, 100, 80, 30);
      btnbbb.setBackground(Color.ORANGE);
      panel.add(btnaaa);
      panel.add(btnbbb);
      btnddd.setBounds(50, 100, 80, 30);
      btnddd.setBackground(Color.ORANGE);
      panel.add(btnddd);
      frame2.add(panel);
      frame2.setSize(535, 250);
      frame2.setLayout(null);
      frame2.setVisible(true);

    }
    if (e.getSource() == c_three[2]) {
      JFrame frame4 = new JFrame("600");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 400, 200);
      panel.setBackground(Color.BLUE);
      JButton question4 = new JButton("The Amazon rainforest provides ___% of Earth's oxygen. ");
      question4.setBounds(50, 100, 160, 100);
      question4.setBackground(Color.ORANGE);
      panel.add(question4);
      btnEE.setBounds(50, 100, 80, 30);
      btnEE.setBackground(Color.ORANGE);
      btnFF.setBounds(50, 100, 80, 30);
      btnFF.setBackground(Color.ORANGE);
      panel.add(btnEE);
      panel.add(btnFF);
      btnGG.setBounds(50, 100, 80, 30);
      btnGG.setBackground(Color.ORANGE);
      panel.add(btnGG);
      btnHH.setBounds(50, 100, 80, 30);
      btnHH.setBackground(Color.ORANGE);
      panel.add(btnHH);
      frame4.add(panel);
      frame4.setSize(535, 250);
      frame4.setLayout(null);
      frame4.setVisible(true);

    } else if (e.getSource() == c_three[3]) {
      JFrame frame3 = new JFrame("800");
      JPanel panel = new JPanel();
      panel.setBounds(55, 55, 600, 800);
      panel.setBackground(Color.BLUE);
      question11.setBounds(50, 100, 160, 180);
      question11.setBackground(Color.ORANGE);
      panel.add(question11);
      btn12.setBounds(50, 100, 80, 30);
      btn12.setBackground(Color.ORANGE);
      btn13.setBounds(50, 100, 80, 30);
      btn13.setBackground(Color.ORANGE);
      panel.add(btn12);
      panel.add(btn13);
      frame3.add(panel);
      frame3.setSize(800, 300);
      frame3.setLayout(null);
      frame3.setVisible(true);

    }
  }
}

Here is a screenshot of my code: enter image description here

And a picture of the buttons enter image description here

I want it to say your correct or something after a button is clicked so for example in the second screenshot there's a button labelled Nicosia its btn1 so I want btn 1 to do thatthat, I tried an if else but it didn't work; I did if(e.getSource()==btn1){System.out.println("correct")}

Nikolai Shevchenko
  • 7,083
  • 8
  • 33
  • 42
  • Your title implies that you want to place a button visually within another button (which would be a very bad idea), but your last paragraph suggests that you just want to get one of your answer buttons to work properly. It appears you are not calling `btn1.addActionListener(this)` anywhere in your code, so pressing `btn1` never causes the `actionPerformed` method to be invoked. – VGR Dec 18 '21 at 01:27
  • 2
    You don't want buttons within buttons, you want buttons within a container – MadProgrammer Dec 18 '21 at 02:36
  • 1
    Ok, it's taken way more time then it should have to understand what you problem actually is. Essentially, though, you need to decouple the UI from the data/model, as the presentation of the data is very much the same for every question. The questions (and answer) should be distilled into a manageable model, which can be passed to a single view which can present it and manage the user response and based on the model, take appropriate action. For [example](https://stackoverflow.com/questions/31602113/listener-placement-adhering-to-the-traditional-non-mediator-mvc-pattern/31604919#31604919) – MadProgrammer Dec 18 '21 at 02:44
  • And [example](https://stackoverflow.com/questions/30925564/why-is-my-jlabel-not-showing-up/30926625#30926625) – MadProgrammer Dec 18 '21 at 02:44

1 Answers1

3

So, having spent way more time with your code then I might have liked to, the basic answer to your question is - use a ActionListener, check which button was pressed and validate the answer to the question.

About here you should be screaming at me "YES, BUT HOW!?", which is where your actual question begins.

The problem is, you've coupled the data (question/options/answers) to the UI in such away that it's simply not easy to for you do to. Instead, you need to decouple the data (question/options/answer) from the UI, so that the UI becomes much more dumb (and re-usable) and relies on the model/data to tell it what it needs to know.

The follow answer makes use of:

  • Dependency injection
  • Observer pattern
  • Single responsibility principle
  • Information hiding (AKA encapsulation)

software engineering principles. It aims to decouple the "model" (actually models) from the UI in such away that you actually only ever need 3 panels to present ALL the data (the question panel gets dynamically re-used)

Let's start with some basic data...

public interface Question {
    public int getPoints();
    public String getPrompt();
    public String[] getOptions();
    public boolean isCorrect(String answer);
}

public interface Quiz {
    public int getScore();
    public String[] getCatagories();
    public Question[] getQuestionsForCatagory(String category);
    public boolean didAnswerQuestion(Question question, String answer);
}

(nb: It's possible to "hide" the isCorrect method in the Question through a second interface or implementation, but I figured by the time I get to the end of this, you're head would already be spinning)

Ok, so these define the basic, contractual, requirements we need to be able to build a "quiz"

It should be noted that it could be possible to add an observer to the Quiz which could generate notifications when the score changes, but I'm going to leave that to you

The intention of using interface like this is to the hide the implementation detail. This means we could source the quiz information from a file (like a XML and/or JSON) or from a database or even some kind of cloud service.

Speaking of implementations, let's start with something simple

public class DefaultQuiz implements Quiz {

    private Map<String, List<Question>> questions = new HashMap<>();
    private int score;

    public void add(String category, Question[] questions) {
        this.questions.put(category, Arrays.asList(questions));
    }

    @Override
    public boolean didAnswerQuestion(Question question, String answer) {
        if (question.isCorrect(answer)) {
            score += question.getPoints();
            return true;
        }
        
        return false;
    }

    @Override
    public int getScore() {
        return score;
    }

    @Override
    public String[] getCatagories() {
        Set<String> keys = questions.keySet();
        return keys.toArray(new String[keys.size()]);
    }

    @Override
    public Question[] getQuestionsForCatagory(String category) {
        List<Question> values = questions.get(category);
        return values.toArray(new Question[values.size()]);
    }

    public static Quiz build() {
        DefaultQuiz quiz = new DefaultQuiz();
        quiz.add("Oddly Niche Topics", new Question[]{
            new DefaultQuestion(200, "What is the capital of Cyprus?", new String[]{"Nicosia", "Mumbai", "Dubait", "Romania"}, 0),
            new DefaultQuestion(400, "What is a note that is played for half the duration of a thirty second note?", new String[]{"demisemiquaver", "semidemiquaver", "qaver", "stop note"}, 0),
            new DefaultQuestion(600, "How many times was Caesar stabbed by his senators?", new String[]{"23", "27", "72", "4"}, 0),
            new DefaultQuestion(800, "Louisiana is home to a rare pink dolphin named?", new String[]{"Pinky", "Cotten Candy", "Lady", "The Other Tide."}, 0),
        });
        quiz.add("Ominously Enough Teachers", new Question[]{
            new DefaultQuestion(200, "What do teachers know?", new String[]{"Everything about you", "All about the thing in the janitors closet", "If Dubait  is real or not", "12"}, 0),
            new DefaultQuestion(400, "Who is my physics teacher?", new String[]{"Mr. Penny", "Mr. Dime", "Mr. Nickel", "Mr. Dollar"}, 0),
            new DefaultQuestion(600, "How much do teachers get payed on average?", new String[]{"$63,645", "$120,000", "$15", "$64,200"}, 0),
            new DefaultQuestion(800, "For every 10 Canadian teachers, at least 4 have endured violence from students?", new String[]{"True", "False"}, 0),
        });
        quiz.add("Common Miconceptions", new Question[]{
            new DefaultQuestion(200, "The most prolific modern serial killer is?", new String[]{"Everything about you", "All about the thing in the janitors closet", "If Dubait  is real or not", "12"}, 0),
            new DefaultQuestion(400, "Urine is sterile?", new String[]{"Mr. Penny", "Mr. Dime", "Mr. Nickel", "Mr. Dollar"}, 0),
            new DefaultQuestion(600, "The Amazon rainforest provides ___% of Earth's oxygen", new String[]{"$63,645", "$120,000", "$15", "$64,200"}, 0),
            new DefaultQuestion(800, "Apparently this is where the quiz ends", new String[]{"True", "True"}, 0),
        });
        quiz.add("Riddles", new Question[]{
            new DefaultQuestion(200, "What is the meaning of live?", new String[]{"42", "Eat, Drink, Sleep, Repeat", "Grow, get a meaningness job, work till you die", "Parties"}, 0),
            new DefaultQuestion(400, "What's black and white and red all over?", new String[]{"A news paper", "A pengiun with a knife", "A panda with a knife"}, 0),
            new DefaultQuestion(600, "Is this question pointless?", new String[]{"Yes", "No", "Depends on your point of view"}, 0),
            new DefaultQuestion(800, "Why are you stil here?", new String[]{"Pubs are closed", "I want to learn more"}, 0),
        });
        
        return quiz;
    }
}

public class DefaultQuestion implements Question {

    private int points;
    private String prompt;
    private List<String> options;
    private String answer;

    public DefaultQuestion(int points, String prompt, String[] options, int answer) {
        this.points = points;
        this.prompt = prompt;
        this.options = Arrays.asList(options);
        this.answer = options[answer];
    }

    public int getPoints() {
        return points;
    }

    public String getPrompt() {
        return prompt;
    }

    public String[] getOptions() {
        Collections.shuffle(options);
        return options.toArray(new String[options.size()]);
    }

    @Override
    public boolean isCorrect(String answer) {
        return this.answer.equals(answer);
    }

}

So, this default implementation has a simple build method which builds a quiz, based on the information I extracted from your question.

One thing to note is, every time DefaultQuestion#getOptions is called, the options are randomised!! So you, you know, actually have to read the answers

Now, the UI is broken down into three parts, the "categories pane", the "question and answer pane" and the "controller"

The first two are pretty easy to understand, the controller needs a little bit more consideration.

Let's start with the first two...

public class QuizCategoriesPane extends JPanel {
    
    public static interface Observer {
        public void askQuestion(QuizCategoriesPane source, Quiz quize, Question question);
    }
    
    private Quiz quiz;
    private Observer observer;
    
    public QuizCategoriesPane(Quiz quiz, Observer observer) {
        this.quiz = quiz;
        this.observer = observer;
        String[] categories = quiz.getCatagories();
        
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridheight = GridBagConstraints.REMAINDER;
        gbc.insets = new Insets(4, 4, 4, 4);
        gbc.anchor = GridBagConstraints.NORTH;
        
        for (String category : categories) {
            add(makeCategoryPaneFor(category, quiz.getQuestionsForCatagory(category)), gbc);
        }
        
        JButton spinButton = buildButton();
        spinButton.setText("Spin the wheel");
        gbc.fill = GridBagConstraints.HORIZONTAL;
        add(spinButton, gbc);
    }

    public Quiz getQuiz() {
        return quiz;
    }
    
    protected JPanel makeCategoryPaneFor(String category, Question[] questions) {
        JPanel panel = new JPanel(new GridLayout(-1, 1, 4, 4));
        for (Question question : questions) {
            panel.add(makeButtonForQuestion(category, question));
        }
        return panel;
    }
    
    protected JButton makeButtonForQuestion(String category, Question question) {
        JButton btn = buildButton();
        btn.setText(category);
        // I'd prefer to use a Action, but I'm probably already pushing you
        // beyond your limits
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                observer.askQuestion(QuizCategoriesPane.this, getQuiz(), question);
            }
        });
        
        return btn;
    }
    
    protected JButton buildButton() {
        JButton btn = new JButton();
        btn.setContentAreaFilled(false);
        btn.setBorderPainted(false);
        btn.setBackground(Color.BLUE);
        btn.setForeground(Color.YELLOW);  
        btn.setOpaque(true);
        btn.setBorder(new EmptyBorder(32, 32, 32, 32));
        return btn;
    }
    
}

public class QuestionPane extends JPanel {
    
    public static interface Obsever {
        public void didAnswerQuestion(QuestionPane source);
    }
    
    private Quiz quiz;
    private Question question;
    
    private QuestionPane(Quiz quiz, Question question, Obsever obsever) {
        this.question = question;
        setLayout(new BorderLayout());
        
        add(new JLabel("<html>For " + question.getPoints() + " Points<br><h1>" + question.getPrompt() + "</h1></html>"), BorderLayout.NORTH);
        
        JPanel options = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        gbc.anchor = GridBagConstraints.FIRST_LINE_START;
        
        ButtonGroup bg = new ButtonGroup();
        for (String option : question.getOptions()) {
            JRadioButton button = new JRadioButton("<html><h2>" + option + "</h2></html>");
            button.setActionCommand(option);
            bg.add(button);
            options.add(button, gbc);
        }
        add(options);
        
        JPanel actionPane = new JPanel(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        gbc.anchor = GridBagConstraints.LINE_END;
        
        JButton answerButton = new JButton("Answer");
        answerButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String answer = bg.getSelection().getActionCommand();
                if (quiz.didAnswerQuestion(question, answer)) {
                    JOptionPane.showMessageDialog(QuestionPane.this, "Correct");
                } else {
                    JOptionPane.showMessageDialog(QuestionPane.this, "Incorrect");
                }
                obsever.didAnswerQuestion(QuestionPane.this);
            }
        });
        actionPane.add(answerButton, gbc);
        
        add(actionPane, BorderLayout.SOUTH);
    }
}

The "controller" is responsible for managing the presentation of the "categories" and the "question/answer" UIs. Because the UIs are relatively complicated, they are separated into individual classes, this allows them to be responsible for just doing one job and not getting over burden with functionality which really isn't their responsibility anyway.

The controller might look something like...

public class QuizPane extends JPanel {

    private CardLayout cardLayout;
    
    public QuizPane(Quiz quiz) {
        setBorder(new EmptyBorder(16, 16, 16, 16));
        cardLayout = new CardLayout();
        setLayout(cardLayout);
        
        QuizCategoriesPane.Observer quizObserver = new QuizCategoriesPane.Observer() {
            @Override
            public void askQuestion(QuizCategoriesPane source, Quiz quize, Question question) {
                QuestionPane qp = new QuestionPane(quiz, question, new QuestionPane.Obsever() {
                    @Override
                    public void didAnswerQuestion(QuestionPane source) {
                        remove(source);
                        cardLayout.show(QuizPane.this, "categories");
                    }
                });
                add(qp, "question");
                cardLayout.show(QuizPane.this, "question");
            }
        };
        
        add(new QuizCategoriesPane(quiz, quizObserver), "categories");
    }
    
}

It has a very basic responsibility, show the user the categories, when a user selects a category, notified via an observer, show the question. When the user answers the question, notified via an observer, show the categories again.

As I said earlier, somebody needs to tell the categories pane that the score has changed, I've suggested that this could be done via an observer pattern on the Quiz itself, as this makes it independent of all the other workflows. And, no, I'm not going to do it.

Now, obviously, this needs some more work, for example, there's no way to track which questions have already been presented to the user, something else for you to figure out

Runnable example

enter image description here

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.EmptyBorder;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Quiz quiz = DefaultQuiz.build();
                JFrame frame = new JFrame();
                frame.add(new QuizPane(quiz));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static interface Question {
        public int getPoints();
        public String getPrompt();
        public String[] getOptions();
        public boolean isCorrect(String answer);
    }

    public static interface Quiz {
        public int getScore();
        public String[] getCatagories();
        public Question[] getQuestionsForCatagory(String category);
        public boolean didAnswerQuestion(Question question, String answer);
    }

    public static class DefaultQuiz implements Quiz {

        private Map<String, List<Question>> questions = new HashMap<>();
        private int score;

        public void add(String category, Question[] questions) {
            this.questions.put(category, Arrays.asList(questions));
        }

        @Override
        public boolean didAnswerQuestion(Question question, String answer) {
            if (question.isCorrect(answer)) {
                score += question.getPoints();
                return true;
            }

            return false;
        }

        @Override
        public int getScore() {
            return score;
        }

        @Override
        public String[] getCatagories() {
            Set<String> keys = questions.keySet();
            return keys.toArray(new String[keys.size()]);
        }

        @Override
        public Question[] getQuestionsForCatagory(String category) {
            List<Question> values = questions.get(category);
            return values.toArray(new Question[values.size()]);
        }

        public static Quiz build() {
            DefaultQuiz quiz = new DefaultQuiz();
            quiz.add("Oddly Niche Topics", new Question[]{
                new DefaultQuestion(200, "What is the capital of Cyprus?", new String[]{"Nicosia", "Mumbai", "Dubait", "Romania"}, 0),
                new DefaultQuestion(400, "What is a note that is played for half the duration of a thirty second note?", new String[]{"demisemiquaver", "semidemiquaver", "qaver", "stop note"}, 0),
                new DefaultQuestion(600, "How many times was Caesar stabbed by his senators?", new String[]{"23", "27", "72", "4"}, 0),
                new DefaultQuestion(800, "Louisiana is home to a rare pink dolphin named?", new String[]{"Pinky", "Cotten Candy", "Lady", "The Other Tide."}, 0),
            });
            quiz.add("Ominously Enough Teachers", new Question[]{
                new DefaultQuestion(200, "What do teachers know?", new String[]{"Everything about you", "All about the thing in the janitors closet", "If Dubait  is real or not", "12"}, 0),
                new DefaultQuestion(400, "Who is my physics teacher?", new String[]{"Mr. Penny", "Mr. Dime", "Mr. Nickel", "Mr. Dollar"}, 0),
                new DefaultQuestion(600, "How much do teachers get payed on average?", new String[]{"$63,645", "$120,000", "$15", "$64,200"}, 0),
                new DefaultQuestion(800, "For every 10 Canadian teachers, at least 4 have endured violence from students?", new String[]{"True", "False"}, 0),
            });
            quiz.add("Common Miconceptions", new Question[]{
                new DefaultQuestion(200, "The most prolific modern serial killer is?", new String[]{"Everything about you", "All about the thing in the janitors closet", "If Dubait  is real or not", "12"}, 0),
                new DefaultQuestion(400, "Urine is sterile?", new String[]{"Mr. Penny", "Mr. Dime", "Mr. Nickel", "Mr. Dollar"}, 0),
                new DefaultQuestion(600, "The Amazon rainforest provides ___% of Earth's oxygen", new String[]{"$63,645", "$120,000", "$15", "$64,200"}, 0),
                new DefaultQuestion(800, "Apparently this is where the quiz ends", new String[]{"True", "True"}, 0),
            });
            quiz.add("Riddles", new Question[]{
                new DefaultQuestion(200, "What is the meaning of live?", new String[]{"42", "Eat, Drink, Sleep, Repeat", "Grow, get a meaningness job, work till you die", "Parties"}, 0),
                new DefaultQuestion(400, "What's black and white and red all over?", new String[]{"A news paper", "A pengiun with a knife", "A panda with a knife"}, 0),
                new DefaultQuestion(600, "Is this question pointless?", new String[]{"Yes", "No", "Depends on your point of view"}, 0),
                new DefaultQuestion(800, "Why are you stil here?", new String[]{"Pubs are closed", "I want to learn more"}, 0),
            });

            return quiz;
        }
    }

    public static class DefaultQuestion implements Question {

        private int points;
        private String prompt;
        private List<String> options;
        private String answer;

        public DefaultQuestion(int points, String prompt, String[] options, int answer) {
            this.points = points;
            this.prompt = prompt;
            this.options = Arrays.asList(options);
            this.answer = options[answer];
        }

        public int getPoints() {
            return points;
        }

        public String getPrompt() {
            return prompt;
        }

        public String[] getOptions() {
            Collections.shuffle(options);
            return options.toArray(new String[options.size()]);
        }

        @Override
        public boolean isCorrect(String answer) {
            return this.answer.equals(answer);
        }

    }

    public static class QuizPane extends JPanel {

        private CardLayout cardLayout;

        public QuizPane(Quiz quiz) {
            setBorder(new EmptyBorder(16, 16, 16, 16));
            cardLayout = new CardLayout();
            setLayout(cardLayout);

            QuizCategoriesPane.Observer quizObserver = new QuizCategoriesPane.Observer() {
                @Override
                public void askQuestion(QuizCategoriesPane source, Quiz quize, Question question) {
                    QuestionPane qp = new QuestionPane(quiz, question, new QuestionPane.Obsever() {
                        @Override
                        public void didAnswerQuestion(QuestionPane source) {
                            remove(source);
                            cardLayout.show(QuizPane.this, "categories");
                        }
                    });
                    add(qp, "question");
                    cardLayout.show(QuizPane.this, "question");
                }
            };

            add(new QuizCategoriesPane(quiz, quizObserver), "categories");
        }

    }

    public static class QuizCategoriesPane extends JPanel {

        public static interface Observer {
            public void askQuestion(QuizCategoriesPane source, Quiz quize, Question question);
        }

        private Quiz quiz;
        private Observer observer;

        public QuizCategoriesPane(Quiz quiz, Observer observer) {
            this.quiz = quiz;
            this.observer = observer;
            String[] categories = quiz.getCatagories();

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.gridheight = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(4, 4, 4, 4);
            gbc.anchor = GridBagConstraints.NORTH;

            for (String category : categories) {
                add(makeCategoryPaneFor(category, quiz.getQuestionsForCatagory(category)), gbc);
            }

            JButton spinButton = buildButton();
            spinButton.setText("Spin the wheel");
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(spinButton, gbc);
        }

        public Quiz getQuiz() {
            return quiz;
        }

        protected JPanel makeCategoryPaneFor(String category, Question[] questions) {
            JPanel panel = new JPanel(new GridLayout(-1, 1, 4, 4));
            for (Question question : questions) {
                panel.add(makeButtonForQuestion(category, question));
            }
            return panel;
        }

        protected JButton makeButtonForQuestion(String category, Question question) {
            JButton btn = buildButton();
            btn.setText(category);
            // I'd prefer to use a Action, but I'm probably already pushing you
            // beyond your limits
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    observer.askQuestion(QuizCategoriesPane.this, getQuiz(), question);
                }
            });

            return btn;
        }

        protected JButton buildButton() {
            JButton btn = new JButton();
            btn.setContentAreaFilled(false);
            btn.setBorderPainted(false);
            btn.setBackground(Color.BLUE);
            btn.setForeground(Color.YELLOW);  
            btn.setOpaque(true);
            btn.setBorder(new EmptyBorder(32, 32, 32, 32));
            return btn;
        }

    }

    public static class QuestionPane extends JPanel {

        public static interface Obsever {
            public void didAnswerQuestion(QuestionPane source);
        }

        private Quiz quiz;
        private Question question;

        private QuestionPane(Quiz quiz, Question question, Obsever obsever) {
            this.question = question;
            setLayout(new BorderLayout());

            add(new JLabel("<html>For " + question.getPoints() + " Points<br><h1>" + question.getPrompt() + "</h1></html>"), BorderLayout.NORTH);

            JPanel options = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.FIRST_LINE_START;

            ButtonGroup bg = new ButtonGroup();
            for (String option : question.getOptions()) {
                JRadioButton button = new JRadioButton("<html><h2>" + option + "</h2></html>");
                button.setActionCommand(option);
                bg.add(button);
                options.add(button, gbc);
            }
            add(options);

            JPanel actionPane = new JPanel(new GridBagLayout());
            gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.LINE_END;

            JButton answerButton = new JButton("Answer");
            answerButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    String answer = bg.getSelection().getActionCommand();
                    if (quiz.didAnswerQuestion(question, answer)) {
                        JOptionPane.showMessageDialog(QuestionPane.this, "Correct");
                    } else {
                        JOptionPane.showMessageDialog(QuestionPane.this, "Incorrect");
                    }
                    obsever.didAnswerQuestion(QuestionPane.this);
                }
            });
            actionPane.add(answerButton, gbc);

            add(actionPane, BorderLayout.SOUTH);
        }
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • how exactly did u implement this bc when I tried it, it didn't really work? like for example the public interface Question code and such, was it its own separate class? I tried copying and pasting this and it didn't work? – Zainab Sajjad Dec 19 '21 at 02:27
  • 1
    The “runnable” example should be just copy and paste (into a single file) - I do this because it’s easier for demonstration purposes, but ideally, a proper solution would hae them in their own files – MadProgrammer Dec 19 '21 at 06:50