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中按钮内的按钮的主要内容,如果未能解决你的问题,请参考以下文章
使用 GridLayout 内的按钮将 BoxLayout 居中
JAVA的GUI中如何实现按下某个按钮后关闭当前窗口,打开新的窗口?