单击 6 次后 CardLayout 按钮发生变化
CardLayout button changes after 6 clicks
我正在尝试创建一个测验。测验从阅读文件开始。该文件有 6 个问题。每个问题在卡片布局中都有自己的卡片。每张卡片都有一个指向下一个 CardLayout 的按钮。问题 1 - 5 应该有一个 'next' 按钮,可以 link 转到下一张卡片。问题 6 应该有一个按钮,上面写着 'get results' 这将 link 到一张显示可能结果卡片之一的卡片。 (这些仍在进行中,现在我只是试图创建按钮并使用 .previous() 方法对其进行测试)。截至目前,每张卡片都有一个下一个按钮,似乎没有达到添加 'get results' 按钮的声明。看一看。
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class UserInterface extends JPanel {
public static final Object QUESTION = "question";
// fill label with blank text to expand it
private JLabel resultLabel = new JLabel(String.format("%150s", " "));
// CardLayout to allow swapping of question panels
private CardLayout cardLayout = new CardLayout();
private JPanel centerPanel = new JPanel(cardLayout);
private List<String> answers = new ArrayList<>();
private int currentCard = 0;
private QuestionsContainer containers = new QuestionsContainer();
public UserInterface(QuestionsContainer container) throws FileNotFoundException {
centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (Questions question : container.getQuestions()) {
centerPanel.add(createQPanel(question), null);
currentCard++;
JPanel bottomPanel = new JPanel(new BorderLayout());
if ((currentCard == containers.questionsLength() - 1){
bottomPanel.add(new JButton(new AbstractAction("Next") {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(centerPanel);
}
}),
BorderLayout.LINE_START);
add(bottomPanel, BorderLayout.LINE_START);
bottomPanel.add(resultLabel);
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.PAGE_END);
add(centerPanel);
}
JPanel bottomPanel1 = new JPanel();
bottomPanel1.add(new JButton(new AbstractAction("Get Results") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("hello");
cardLayout.previous(centerPanel);
// both of these are just to see if this statement is reached
bottomPanel.validate();
bottomPanel.repaint();
}
}),
BorderLayout.LINE_START);
add(bottomPanel1, BorderLayout.LINE_START);
bottomPanel1.add(resultLabel);
setLayout(new BorderLayout());
add(bottomPanel1, BorderLayout.PAGE_END);
add(centerPanel);
}
}
private JPanel createQPanel(Questions question) {
JPanel radioPanel = new JPanel(new GridLayout(0, 1));
radioPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
radioPanel.add(new JLabel(question.getQuestion()), BorderLayout.PAGE_START);
ButtonGroup buttonGroup = new ButtonGroup();
ItemListener myItemListener = new MyItemListener(this);
for (String answer : question.getAnswer()) {
JRadioButton answerButton = new JRadioButton(answer);
answerButton.putClientProperty(QUESTION, question);
answerButton.addItemListener(myItemListener);
buttonGroup.add(answerButton);
radioPanel.add(answerButton);
}
JPanel qPanel = new JPanel(new BorderLayout());
qPanel.add(radioPanel);
return qPanel;
}
public void displayResult(String selectedText) {
resultLabel.setText(selectedText);
}
public void displayFinalResults(){
}
public static void createAndShowGui() throws FileNotFoundException {
UserInterface mainPanel = new UserInterface(new QuestionsContainer());
JFrame frame = new JFrame("User Interface");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class QuestionsContainer {
private List<Questions> questions = new ArrayList<>();
private int questionCount = 0;
QuestionsContainer() throws FileNotFoundException {
File file = new File("src/house1.txt");
try (Scanner reader = new Scanner(file)) {
String question = "";
List<String> answers = new ArrayList<>();
while (reader.hasNextLine()){
String line = reader.nextLine();
if (line.startsWith("QUESTION: ")) {
question = line.substring(10);
} else if (line.startsWith("ANSWER: ")){
String answer = line.substring(8);
answers.add(answer);
} else if (line.isEmpty()) {
questions.add(new Questions(question, answers));
question = "";
answers = new ArrayList<>();
questionCount++;
}
}
}
}
public List<Questions> getQuestions() {
return questions;
}
public int questionsLength(){
return questions.size();
}
我试过使 bottomPanel 成为它自己的返回 bottomPanel 的方法。这没有达到预期的结果,因为它是在构造函数中调用的,而且我认为 currentCard 变量并不是每次都加起来。
现在这段代码可以很好地读取所有问题和所有答案。但它会在每张卡片上创建一个下一个按钮,而不仅仅是前 5 张。如果在一个奇怪的地方有一个变量或一个可疑的打印调用,它很可能是我忘记 delete/comment 的先前测试的剩余代码。
您似乎是在考虑程序过程,而不是事件驱动过程。 currentCard
的状态将在每次循环期间更新,它的状态不是 "stored" 在迭代之间。
这意味着,作为 BorderLayout
的副作用,只会显示最后添加到容器中的组件。
相反,你需要改变你的想法,这样当ActionListener
被触发时,你更新状态并决定应该做什么,例如
public UserInterface(QuestionsContainer container) throws FileNotFoundException {
setLayout(new BorderLayout());
centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (Questions question : container.getQuestions()) {
centerPanel.add(createQPanel(question), null);
}
add(centerPanel);
JPanel navigationPane = new JPanel(new GridBagLayout());
navigationPane.setBorder(new EmptyBorder(8, 8, 8, 8));
JButton navButton = new JButton("Next");
navButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("Next")) {
currentCard++;
if (currentCard == container.questionsLength()) {
((JButton) evt.getSource()).setText("Get results");
}
cardLayout.next(centerPanel);
} else {
System.out.println("Print the results");
}
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 1;
navigationPane.add(navButton, gbc);
add(navigationPane, BorderLayout.SOUTH);
}
我正在尝试创建一个测验。测验从阅读文件开始。该文件有 6 个问题。每个问题在卡片布局中都有自己的卡片。每张卡片都有一个指向下一个 CardLayout 的按钮。问题 1 - 5 应该有一个 'next' 按钮,可以 link 转到下一张卡片。问题 6 应该有一个按钮,上面写着 'get results' 这将 link 到一张显示可能结果卡片之一的卡片。 (这些仍在进行中,现在我只是试图创建按钮并使用 .previous() 方法对其进行测试)。截至目前,每张卡片都有一个下一个按钮,似乎没有达到添加 'get results' 按钮的声明。看一看。
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class UserInterface extends JPanel {
public static final Object QUESTION = "question";
// fill label with blank text to expand it
private JLabel resultLabel = new JLabel(String.format("%150s", " "));
// CardLayout to allow swapping of question panels
private CardLayout cardLayout = new CardLayout();
private JPanel centerPanel = new JPanel(cardLayout);
private List<String> answers = new ArrayList<>();
private int currentCard = 0;
private QuestionsContainer containers = new QuestionsContainer();
public UserInterface(QuestionsContainer container) throws FileNotFoundException {
centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (Questions question : container.getQuestions()) {
centerPanel.add(createQPanel(question), null);
currentCard++;
JPanel bottomPanel = new JPanel(new BorderLayout());
if ((currentCard == containers.questionsLength() - 1){
bottomPanel.add(new JButton(new AbstractAction("Next") {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(centerPanel);
}
}),
BorderLayout.LINE_START);
add(bottomPanel, BorderLayout.LINE_START);
bottomPanel.add(resultLabel);
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.PAGE_END);
add(centerPanel);
}
JPanel bottomPanel1 = new JPanel();
bottomPanel1.add(new JButton(new AbstractAction("Get Results") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("hello");
cardLayout.previous(centerPanel);
// both of these are just to see if this statement is reached
bottomPanel.validate();
bottomPanel.repaint();
}
}),
BorderLayout.LINE_START);
add(bottomPanel1, BorderLayout.LINE_START);
bottomPanel1.add(resultLabel);
setLayout(new BorderLayout());
add(bottomPanel1, BorderLayout.PAGE_END);
add(centerPanel);
}
}
private JPanel createQPanel(Questions question) {
JPanel radioPanel = new JPanel(new GridLayout(0, 1));
radioPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
radioPanel.add(new JLabel(question.getQuestion()), BorderLayout.PAGE_START);
ButtonGroup buttonGroup = new ButtonGroup();
ItemListener myItemListener = new MyItemListener(this);
for (String answer : question.getAnswer()) {
JRadioButton answerButton = new JRadioButton(answer);
answerButton.putClientProperty(QUESTION, question);
answerButton.addItemListener(myItemListener);
buttonGroup.add(answerButton);
radioPanel.add(answerButton);
}
JPanel qPanel = new JPanel(new BorderLayout());
qPanel.add(radioPanel);
return qPanel;
}
public void displayResult(String selectedText) {
resultLabel.setText(selectedText);
}
public void displayFinalResults(){
}
public static void createAndShowGui() throws FileNotFoundException {
UserInterface mainPanel = new UserInterface(new QuestionsContainer());
JFrame frame = new JFrame("User Interface");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class QuestionsContainer {
private List<Questions> questions = new ArrayList<>();
private int questionCount = 0;
QuestionsContainer() throws FileNotFoundException {
File file = new File("src/house1.txt");
try (Scanner reader = new Scanner(file)) {
String question = "";
List<String> answers = new ArrayList<>();
while (reader.hasNextLine()){
String line = reader.nextLine();
if (line.startsWith("QUESTION: ")) {
question = line.substring(10);
} else if (line.startsWith("ANSWER: ")){
String answer = line.substring(8);
answers.add(answer);
} else if (line.isEmpty()) {
questions.add(new Questions(question, answers));
question = "";
answers = new ArrayList<>();
questionCount++;
}
}
}
}
public List<Questions> getQuestions() {
return questions;
}
public int questionsLength(){
return questions.size();
}
我试过使 bottomPanel 成为它自己的返回 bottomPanel 的方法。这没有达到预期的结果,因为它是在构造函数中调用的,而且我认为 currentCard 变量并不是每次都加起来。 现在这段代码可以很好地读取所有问题和所有答案。但它会在每张卡片上创建一个下一个按钮,而不仅仅是前 5 张。如果在一个奇怪的地方有一个变量或一个可疑的打印调用,它很可能是我忘记 delete/comment 的先前测试的剩余代码。
您似乎是在考虑程序过程,而不是事件驱动过程。 currentCard
的状态将在每次循环期间更新,它的状态不是 "stored" 在迭代之间。
这意味着,作为 BorderLayout
的副作用,只会显示最后添加到容器中的组件。
相反,你需要改变你的想法,这样当ActionListener
被触发时,你更新状态并决定应该做什么,例如
public UserInterface(QuestionsContainer container) throws FileNotFoundException {
setLayout(new BorderLayout());
centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (Questions question : container.getQuestions()) {
centerPanel.add(createQPanel(question), null);
}
add(centerPanel);
JPanel navigationPane = new JPanel(new GridBagLayout());
navigationPane.setBorder(new EmptyBorder(8, 8, 8, 8));
JButton navButton = new JButton("Next");
navButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("Next")) {
currentCard++;
if (currentCard == container.questionsLength()) {
((JButton) evt.getSource()).setText("Get results");
}
cardLayout.next(centerPanel);
} else {
System.out.println("Print the results");
}
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 1;
navigationPane.add(navButton, gbc);
add(navigationPane, BorderLayout.SOUTH);
}