java GUI中按钮内的按钮

Posted

技术标签:

【中文标题】java GUI中按钮内的按钮【英文标题】:Buttons within buttons in java GUI 【发布时间】:2022-01-20 18:50:48 【问题描述】:

我想在 java gui 的按钮中创建按钮,所以我有一堆按钮,在这些按钮中还有更多按钮,但是每当我尝试为这些按钮创建一个 for 循环时,什么都没有发生。这是我的代码

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);

    
  

这是我的代码截图:

还有按钮的图片

我希望它在单击按钮后说出您的正确或其他内容,例如,在第二个屏幕截图中,有一个标记为 Nicosia 它的 btn1 的按钮,所以我希望 btn 1 这样做,我尝试了 if else 但它没有工作;我做了 if(e.getSource()==btn1)System.out.println("correct")

【问题讨论】:

您的标题暗示您想在另一个按钮中直观地放置一个按钮(这将是一个非常糟糕的主意),但您的最后一段表明您只想让一个答案按钮工作适当地。看来您没有在代码中的任何位置调用btn1.addActionListener(this),因此按btn1 永远不会导致调用actionPerformed 方法。 你不想要按钮中的按钮,你想要容器中的按钮 好的,它需要更多的时间,然后它应该必须了解您的问题实际上是什么。但是,本质上,您需要将 UI 与数据/模型分离,因为每个问题的数据呈现方式都非常相似。问题(和答案)应该被提炼成一个可管理的模型,该模型可以传递给一个单一的视图,该视图可以呈现它并管理用户响应,并基于该模型采取适当的行动。对于example 还有example 【参考方案1】:

因此,在您的代码上花费了我可能喜欢的更多时间,您问题的基本答案是 - 使用 ActionListener,检查按下了哪个按钮并验证问题的答案。

关于这里,您应该对我大喊“是的,但是如何!?”,这是您实际问题的开始。

问题是,您已经将数据(问题/选项/答案)耦合到 UI 的距离太远了,这对您来说并不容易。相反,您需要将数据(问题/选项/答案)与 UI 分离,以便 UI 变得更加愚蠢(并且可重用)并依赖模型/数据来告诉它需要知道的内容。

以下答案使用:

依赖注入 观察者模式 单一责任原则 信息隐藏(AKA 封装)

软件工程原理。它旨在将“模型”(实际上是模型)与 UI 分离,这样您实际上只需要 3 个面板来呈现所有数据(问题面板被动态重用)

让我们从一些基本数据开始...

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: 可以通过第二个interface 或实现在Question 中“隐藏”isCorrect 方法,但我想在我结束时,你' re head 已经在旋转了

好的,所以这些定义了我们构建“测验”所需的基本合同要求

应该注意的是,可以向Quiz 添加观察者,这可以在分数发生变化时生成通知,但我将把它留给你 ?

像这样使用interface 的目的是隐藏实现细节。这意味着我们可以从文件(如 XML 和/或 JSON)或数据库甚至某种云服务中获取测验信息。

说到实现,让我们从简单的开始

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);
    


所以,这个默认实现有一个简单的build 方法,它根据我从您的问题中提取的信息构建一个测验。

需要注意的是,每次调用DefaultQuestion#getOptions 时,选项都是随机的!!所以你,你知道的,实际上必须阅读答案?

现在,UI 分为三个部分,“类别窗格”、“问答窗格”和“控制器”

前两个很容易理解,控制器需要多一点考虑。

让我们从前两个开始...

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);
    

“控制器”负责管理“类别”和“问题/答案”用户界面的呈现。由于 UI 相对复杂,它们被分成单独的类,这使它们可以只负责完成一项工作,而不会因为功能负担过重,而这实际上并不是他们的责任。

控制器可能看起来像...

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");
    
    

它有一个非常基本的职责,向用户显示类别,当用户选择一个类别时,通过观察者通知,显示问题。当用户回答问题时,通过观察者通知,再次显示类别。

正如我之前所说,有人需要告诉类别窗格分数已经改变,我建议这可以通过Quiz 本身的观察者模式来完成,因为这使它独立于所有其他工作流程。而且,不,我不会这样做。

现在,显然,这需要做更多的工作,例如,无法跟踪哪些问题已经呈现给用户,还有其他事情需要你弄清楚?

可运行示例

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);
        
    

【讨论】:

当我尝试它时,你究竟是如何实现这个 bc 的,它并没有真正起作用?例如公共接口问题代码等,它是它自己的单独类吗?我尝试复制和粘贴此内容,但没有成功? “可运行”示例应该只是复制和粘贴(到单个文件中) - 我这样做是因为它更容易用于演示目的,但理想情况下,适当的解决方案会将它们放在自己的文件中

以上是关于java GUI中按钮内的按钮的主要内容,如果未能解决你的问题,请参考以下文章

java GUI编程(swing)之二swing按钮组件

使用 GridLayout 内的按钮将 BoxLayout 居中

JAVA的GUI中如何实现按下某个按钮后关闭当前窗口,打开新的窗口?

JAVA GUI问题。如何触动按钮后弹出文件浏览器和文件名选择框,选择保存目录?

Java Gui 设计模式中的事件监听

写一个java GUI界面,有个文本框可输入文本,按个按钮之后输出到文件中