2015-12-08 1 views
1

Я пишу программу, в которой есть элемент викторины, и когда пользователь получает ответ неправильно, дается обратная связь. Вопрос JFrame сделан из JLabel, у которого есть реальный вопрос, и 4 JRadioButtons, которые имеют разные варианты (называемые rad1, rad2, rad3, rad4). То, что я пытаюсь сделать, - это если пользователь ошибается, переключатель с цветом фона правильного ответа становится зеленым, а радиокнопка с ответом на то, что фон пользователя дал красный цвет..setBackground() метод не работает для JRadioButton

Вот цикл, который я использую, чтобы выяснить, какой из ответов является правильным:

private void btnSubmitActionPerformed(java.awt.event.ActionEvent evt) {           
    System.out.println("Submit Clicked"); 
    //figures out what choice the user selected 
    String correctAnswer = questions.get(current).getAnswer(); 
    int numChoice = -1; 
    String choice = ""; 
    boolean answered = false; 

    if (rad1.isSelected()) { 
     numChoice = 0; 
     answered = true; 
     choice = rad1.getText(); 
    } else if (rad2.isSelected()) { 
     numChoice = 1; 
     answered = true; 
     choice = rad2.getText(); 
    } else if (rad3.isSelected()) { 
     numChoice = 2; 
     answered = true; 
     choice = rad3.getText(); 
    } else if (rad4.isSelected()) { 
     numChoice = 3; 
     answered = true; 
     choice = rad4.getText(); 
    } else { //user didn't pick a choice 
     JOptionPane.showMessageDialog(null, "You didn't answer the question, try again!"); 
    } 

    if (choice.equals(correctAnswer)) { 
     score++; 
     System.out.println("score++"); 
    } else { 
     //figures out which of the answers was correct 
     rad1.setBackground(Color.RED); 
     for (int i = 0; i < 4; i++) { 
      if (questions.get(current).getChoices()[i].equals(correctAnswer)) { 
       System.out.println(correctAnswer); 
       System.out.println(i); 
       //me trying to see if it will change if I put it outside the switch 
       //confirmed that it will not. 
       rad1.setBackground(Color.RED); 
       switch (i) { 
        case 0: 
         rad1.setBackground(new Color(51, 204, 51)); 
         break; 
        case 1: 
         rad2.setBackground(new Color(51, 204, 51)); 
         break; 
        case 2: 
         rad3.setBackground(new Color(51, 204, 51)); 
         break; 
        case 3: 
         rad4.setBackground(new Color(51, 204, 51)); 
         break; 
       } 
       break; 
      } 

     } 
     switch (numChoice) { 
      case 0: 
       rad1.setBackground(new Color(153, 0, 0)); 
       break; 
      case 1: 
       rad2.setBackground(new Color(153, 0, 0)); 
       break; 
      case 2: 
       rad3.setBackground(new Color(153, 0, 0)); 
       break; 
      case 3: 
       rad4.setBackground(new Color(153, 0, 0)); 
       break; 
     } 
    } 
    //loads next question 


    //loads the next question 
    if (current < 10) { 
     updateFrame(); 
    } else { 
     //ends the quiz 
    } 
}      

Я играл вокруг с помощью метода .setBackground() на некоторое время, и если я выставлять инструкции печати в блоках case, они выполняются, но раскраски не происходит. Есть что-то немое, что мне не хватает?

Благодаря

EDIT: Добавлено больше кода, чтобы увидеть, что цикл находится в методе btnSubmitActionPerformed(). Когда пользователь нажимает кнопку, их ответ должен быть оценен, а цвет переключателя должен быть изменен.

+0

Рассмотрим обеспечение [работоспособный пример] (https://stackoverflow.com/help/mcve), который демонстрирует вашу проблему. Это не дамп кода, а пример того, что вы делаете, что подчеркивает проблему, с которой вы сталкиваетесь. Это приведет к меньшему путанице и лучшим ответам – MadProgrammer

ответ

1

Вы считаете, что код чрезмерно и излишне сложный. Я сам, я бы попытаться «ООП-римент» вещи, чтобы уменьшить сложность цикломатической и имеет

  • nonGUI Вопрос класс,
  • с полем для струнного questionText,
  • с полем для струнного CorrectAnswer,
  • с List<String> для неправильных измерений.
  • я дам ему метод, скажем public List<String> getShuffledAnswers() возвращать список строк со всеми ответами, правильным и неправильным, перемешиваются в их собственном списке,
  • Логический метод testAnswer(String test), и возвращает истину тестируемых равных правильный ответ.

Я затем создать JPanel называется QuestionPanel

  • , который имеет поле Вопрос
  • , который отображает информацию одного объекта, включая в questionText в JLabel и все перемешиваются ответы в JRadioButtons.
  • Это будет иметь методы для получения выбранного JRadioButton и для получения Вопроса,
  • И способ установки делает фон JRadioButton, непрозрачным при необходимости, с помощью вызова `setOpaque (ложь)
  • И метод что позволяет вызывающему коду устанавливать фон для выбора JRadioButtons с правильным цветом ответа или неправильным цветом ответа.

Например:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 

import javax.swing.AbstractAction; 
import javax.swing.BorderFactory; 
import javax.swing.ButtonGroup; 
import javax.swing.ButtonModel; 
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.SwingUtilities; 

@SuppressWarnings("serial") 
public class TestQuestions extends JPanel { 
    private static final Question TEST_QUESTION = new Question("Select the Correct Answer", "This answer is correct", 
      "Incorrect Answer 1", "Incorrect Answer 2", "Incorrect Answer 3"); 
    private QuestionPanel questionPanel = new QuestionPanel(); 

    public TestQuestions() { 
     questionPanel.setQuestion(TEST_QUESTION); 
     JButton testAnswerBtn = new JButton(new AbstractAction("Test Answer") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       boolean isCorrect = questionPanel.isCorrectAnswerSelected(); 
       String message = ""; 
       if (isCorrect) { 
        message = "Correct answer selected!"; 
       } else { 
        message = "Incorrect answer selected!";      
       } 
       JOptionPane.showMessageDialog(TestQuestions.this, message); 
       questionPanel.displayCorrectWrongAnswers(); 
      } 
     }); 
     JButton clearAllBtn = new JButton(new AbstractAction("Clear All") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       questionPanel.clearAll(); 
       questionPanel.clearSelection(); 
      } 
     }); 

     JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5)); 
     btnPanel.add(testAnswerBtn); 
     btnPanel.add(clearAllBtn); 

     setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
     setLayout(new BorderLayout(5, 5)); 
     add(questionPanel, BorderLayout.CENTER); 
     add(btnPanel, BorderLayout.PAGE_END); 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("TestQuestions"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new TestQuestions()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class QuestionPanel extends JPanel { 
    private static final Color CORRECT_ANSWER_SELECTED_COLOR = new Color(151, 255, 151); 
    private static final Color CORRECT_ANSWER_NOT_SELECTED_COLOR = new Color(151,151, 255); 
    private static final Color INCORRECT_ANSWER_SELECTED_COLOR = new Color(255, 151, 151); 
    private Question question; 
    private JLabel questionTextLabel = new JLabel(); 
    private List<JRadioButton> answerButtonList = new ArrayList<>(); 
    private JPanel answerPanel = new JPanel(new GridLayout(0, 1)); 
    private ButtonGroup buttonGroup = new ButtonGroup(); 

    public QuestionPanel() { 
     setLayout(new BorderLayout()); 
     add(questionTextLabel, BorderLayout.PAGE_START); 
     add(answerPanel, BorderLayout.CENTER); 
    } 

    public void setQuestion(Question question) { 
     this.question = question; 
     questionTextLabel.setText(question.getQuestionText()); 

     answerPanel.removeAll(); 
     answerButtonList.clear(); 
     buttonGroup = new ButtonGroup(); 

     for (String answer : question.getShuffledAnswers()) { 
      JRadioButton rBtn = new JRadioButton(answer); 
      rBtn.setActionCommand(answer); 
      answerButtonList.add(rBtn); 
      buttonGroup.add(rBtn); 
      answerPanel.add(rBtn); 
     } 
    } 

    public boolean isCorrectAnswerSelected() { 
     ButtonModel model = buttonGroup.getSelection(); 
     if (model == null) { 
      return false; // nothing selected 
     } else { 
      return question.checkAnswer(model.getActionCommand()); 
     } 
    } 

    public void clearAll() { 
     for (JRadioButton jRadioButton : answerButtonList) { 
      jRadioButton.setOpaque(false); 
      jRadioButton.setBackground(null); 
     } 
    } 

    public void clearSelection() { 
     buttonGroup.clearSelection(); 
    } 

    public void displayCorrectWrongAnswers() { 
     clearAll(); 
     for (JRadioButton jRadioButton : answerButtonList) { 
      if (jRadioButton.isSelected()) { 
       jRadioButton.setOpaque(true); 
       if (question.checkAnswer(jRadioButton.getActionCommand())) { 
        jRadioButton.setBackground(CORRECT_ANSWER_SELECTED_COLOR); 
       } else { 
        jRadioButton.setBackground(CORRECT_ANSWER_NOT_SELECTED_COLOR); 
       } 
      } else if (question.checkAnswer(jRadioButton.getActionCommand())) { 
       jRadioButton.setOpaque(true); 
       jRadioButton.setBackground(INCORRECT_ANSWER_SELECTED_COLOR); 
      } 
     } 
    } 

} 

class Question { 
    private String questionText; 
    private String correctAnswer; 
    private List<String> incorrectAnswerList = new ArrayList<>(); 
    public Question(String questionText, String correctAnswer, String... incorrectAnswers) { 
     this.questionText = questionText; 
     this.correctAnswer = correctAnswer; 
     for (String incorrectAnswer : incorrectAnswers) { 
      incorrectAnswerList.add(incorrectAnswer); 
     } 
    } 

    public String getQuestionText() { 
     return questionText; 
    } 

    public String getCorrectAnswer() { 
     return correctAnswer; 
    } 

    public List<String> getShuffledAnswers() { 
     List<String> answers = new ArrayList<>(incorrectAnswerList); 
     answers.add(correctAnswer); 
     Collections.shuffle(answers); 
     return answers; 
    } 

    public boolean checkAnswer(String test) { 
     return correctAnswer.equalsIgnoreCase(test); 
    } 

} 
+0

Эй, я ценю всю помощь, которую вы мне дали. Однако я просто споткнулся о решении. Похоже, я слишком много перепутал с перерывом; операторов и коммутаторов. Спасибо за предложения! –

+0

@SamMacpherson: например ... –

+0

ну, я закончил тем, что не выполнил его и изменил способ работы в результате. Но я обнаружил, что если я добавлю JOptionPane.showMessageDialog сразу после того, как радиокнопка должна была изменить цвет, они изменились бы правильно. Удаление операторов JOptionPane заставляет их не работать. Причудливый, подумал я. –

1

Два непосредственных вещи прыгать на ум:

  1. Где код размещен вызывается из? Изменение пользовательских интерфейсов вне рабочего потока Swing является неопределенным. Иногда правильная вещь случается, иногда нет.
  2. Я никогда не пытался устанавливать цвета на переключателях, но кажется вероятным, что у них нет фона.

Попробуйте установить другое свойство, например размер, чтобы увидеть, получился ли у вас результат. Если это так, то проблема в том, что радиокнопки не имеют фона, и вам придется придумать другой дизайн. Если ничего не происходит, то это, вероятно, первая проблема.

+1

JRadioButtons имеет фон, но по умолчанию он не является непрозрачным. Это легко устранить, вызвав 'setOpaque (true)' на JRadioButton. –

+0

Я обнаружил, что могу установить цвет фона в другом методе, который у меня есть, но я не могу установить его в коммутаторе. –