简体   繁体   中英

Java Swing: How to allow user enter Jtextfield again when wrong input?

I'm doing a math quiz game where the questions are generated randomly, and user has to fill in the answer in the jtextfield . Then, when the user press enter button to check answer , the next question will also load in the same form (displayed in the jlabel) for 10 rounds .

But I'm having a problem where I'm using the for loop (to keep generating the questions and prompt user answer for 10 rounds) that it does not allow user to enter answer in textfield after the first question. It skips the gettext() from jtextfield and repeats empty textfield message as the textfield is left blank. Same goes for the repeated catch numberformatexception message when other input than numbers are entered. How do I make the gui get user input in the textfield again for each round for incorrect input?

I have gone through similar tags here and I have tried reading on threads for solution as some suggest in those, but I'm really new to it so I would really appreciate the help. If there is a simple solution than that, I would really love to hear it cause I have been stuck for so long. Thank you so much.

Here is the code:

Variables

double answer=0; //correct answer

double playerans=0d;
String ans;

String mOperation, question;
int no1, no2;
int rounds = 10;
public Game() {
    initComponents();
    this.EasyQuestion(); 
}

Enter button //the problem

    private void enterbtnActionPerformed(java.awt.event.ActionEvent evt) {                                         

   //needs to get user fill textfield then load next question
   for (int i=0; i<rounds; ++i)
  {

    roundlabel.setText(" " + String.valueOf(i + 1));
    boolean valid=false; 

    ans = ansfield.getText().trim(); 
    if (!ansfield.getText().equals(""))
    {
        do
        {
            try
            {
                playerans = Double.parseDouble(ans); //convert to double
            //check player answer- if (Math.abs(Double.parseDouble(answer) - q.answer) <= 0.01) 
            valid = true;

            }catch (NumberFormatException e){ //other input other than integers
                JOptionPane.showMessageDialog(null, "Please enter number only");
                ansfield.setText("");
                valid = false;
                //thread sleep
            }
        } while (!valid);

       if (Math.abs(Double.parseDouble(ans) - this.answer)  <= 0.01) {//for correct answer

                JOptionPane.showMessageDialog(null, "You got it right!"); //mesage to inform player

        }
        else //wrong answers
        {
                 JOptionPane.showMessageDialog(null, "You got it wrong!"); //mesage to inform player

        }

    }
    else
    {
            JOptionPane.showMessageDialog(null, "Empty field");//
    } 

   //generate next question
    EasyQuestion();

    /*open end game form 
    this.close();
    EndGame end = new EndGame();
    end.setVisible(true);
            */
   }//end for

}                                

Math Question generated

//generate math question for easy level
public double EasyQuestion() 
{
    //call method to generate random integers 
    no1 = this.createNum(100); //set range to 100
    no2 = this.createNum(100); 

    //generate random 4 math operations

    int math = createNum (4);
    switch (math){
        case 0: 
            mOperation= "+";
            this.answer = no1 + no2;
            break;

       case 1:
            mOperation = "-";
            this.answer = this.no1 - this.no2;
            break;

        case 2:
            mOperation = "*";
            this.answer = this.no1 * this.no2;
            break;

       default: 
           mOperation = "/";
           //to prevent math error
           while (no2 == 0) {
            this.no2 = this.createNum(100);
            }
           this.answer = 1.0 * this.no1 /this.no2; //to make double num type
           break;

    }
    //display questions
    question =  (no1 + " " + mOperation + " " + no2 + " =  ?");
    qlabel.setText(question);
    ansfield.setText("");
    return this.answer;
}

//generate random number for math integers
public int createNum (int range)
{
    //create instance class Random
    Random rand = new Random();
    int generate = rand.nextInt(range);

    return generate;
}

This is not how event-driven programs work, and what you're trying to do is to shoe-horn linear console programming into an event-driven GUI. The loop in fact is blocking the Swing event thread (the "Event Dispatch Thread or EDT), and this can render your program frozen and useless.

Instead, make your program more event-driven and more "stateful" where it changes how it responds to events based on the state of key "state" fields/variables.

In this situation, you could present the user with 10 JTextFields and ask them to enter data into the fields, and not allow further actions until all fields are filled with appropriate data -- for instance have a "submit" JButton which is disabled, give the JTextFields a DocumentListener that checks content any time a document is changed, and that only enables the submit button once all inputs are valid.

Or you could have an int counter variable, an array of String and a single JTextField, and each time the user submits text, increment the counter and put the String into an appropriate position in the array (or ArrayList)...

In this situation, you'd probably have a non-GUI Question class, one that holds a single question text and its answer. You'd then create a List<Question> questions = new ArrayList<>();` and then using the index int field that I described above, in the ActionListener, accept the input and then advance to displaying next question and display it, again getting rid of the for loop entirely.

Most importantly though, you need to leave linear programming mode and get into the event-driven mindset.


For example:

In the following program, I keep track of which question I am asking with an int state field called index . In the ActionListener, I check if the answer is correct, I then advance the index field via index++ . I then check if there are more question's left by comparing index to the questions array list's size() property,.....

import java.util.*;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;

public class MultipleQuestions extends JPanel {
    private List<Question> questions;
    private JLabel questionLabel = new JLabel();
    private JLabel resultLabel = new JLabel("   ");
    private JTextField answerField = new JTextField(20);
    private JButton submitButton = new JButton("Submit");
    private int index = 0;

    public MultipleQuestions(List<Question> questions) {
        this.questions = questions;

        ActionListener listener = e -> submitListener();
        submitButton.addActionListener(listener);
        answerField.addActionListener(listener);
        submitButton.setMnemonic(KeyEvent.VK_S);

        questionLabel.setText(questions.get(index).getQuestion());

        JPanel questionPanel = new JPanel();
        questionPanel.setBorder(BorderFactory.createTitledBorder("Question"));
        questionPanel.add(questionLabel);

        JPanel resultPanel = new JPanel();
        resultPanel.setBorder(BorderFactory.createTitledBorder("Result"));
        resultPanel.add(resultLabel);

        JPanel answerPanel = new JPanel();
        answerPanel.setBorder(BorderFactory.createTitledBorder("Answer"));
        answerPanel.add(answerField);
        answerPanel.add(submitButton);

        setLayout(new BorderLayout());
        add(questionPanel, BorderLayout.PAGE_START);
        add(resultPanel, BorderLayout.PAGE_END);
        add(answerPanel);
    }

    private void submitListener() {
        String answerText = answerField.getText().trim();
        if (answerText.equals(questions.get(index).getAnswer())) {
            resultLabel.setText("Correct");
        } else {
            resultLabel.setText("incorrect");
        }
        answerField.selectAll();
        answerField.requestFocusInWindow();

        index++;
        if (index >= questions.size()) {
            resultLabel.setText("All Done");
            submitButton.setEnabled(false);
            answerField.setEnabled(false);
        } else {
            questionLabel.setText(questions.get(index).getQuestion());
        }
    }

    public static void main(String[] args) {
        List<Question> questions = Arrays.asList(
            new Question("What is 1 + 1", "2"),
            new Question("What is 1 + 2", "3"),
            new Question("What is 1 + 3", "4"),
            new Question("What is 1 + 4", "5"),
            new Question("What is 1 + 5", "6"),
            new Question("What is 1 + 6", "7")          
        );

        MultipleQuestions multipleQuestions = new MultipleQuestions(questions);
        JFrame frame = new JFrame("Mult Q's");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(multipleQuestions);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);     
    }
}
class Question {
    private String question;
    private String answer;

    public Question(String question, String answer) {
        this.question = question;
        this.answer = answer;       
    }

    public String getQuestion() {
        return question;
    }

    public String getAnswer() {
        return answer;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM