Java Swing: Как разрешить пользователю снова вводить Jtextfield при неправильном вводе? - PullRequest
0 голосов
/ 26 апреля 2020

Я занимаюсь математической викториной , в которой вопросы генерируются случайным образом, и пользователь должен заполнить ответ в поле jtext . Затем, когда пользователь нажимает кнопку ввода до проверки ответа , следующий вопрос *1013* также будет загружен в той же форме (отображается в jlabel) для 10 раундов .

Но у меня возникла проблема, когда я использую для l oop (чтобы продолжать генерировать вопросы и предлагать пользователю ответ в течение 10 раундов) не позволяет пользователю вводить ответ в текстовое поле после первого вопроса. Он пропускает gettext () из jtextfield и повторяет пустое сообщение текстового поля, так как текстовое поле остается пустым. То же самое относится и к повторяющемуся сообщению numberformatexception, когда вводится другой ввод, чем числа Как сделать так, чтобы gui снова получал пользовательский ввод в текстовое поле для каждого раунда при неправильном вводе?

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

Вот код:

Переменные

double answer=0; //correct answer

double playerans=0d;
String ans;

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

Кнопка ввода // Проблема

    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

}                                

Математический Вопрос создан

//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;
}

1 Ответ

1 голос
/ 26 апреля 2020

Это не то, как работают управляемые событиями программы, и вы пытаетесь сделать из линейного программирования консоли в управляемый событиями GUI. Фактически l oop блокирует поток событий Swing («Поток диспетчеризации событий» или EDT), и это может сделать вашу программу замороженной и бесполезной.

Вместо этого сделайте вашу программу более управляемой событиями и более «Stateful», где он меняет то, как он реагирует на события, основываясь на состоянии ключевых «state» полей / переменных.

В этой ситуации вы можете представить пользователю 10 JTextFields и попросить их ввести данные в поля и не разрешать дальнейшие действия до тех пор, пока все поля не будут заполнены соответствующими данными - например, иметь JButton «submit», который отключен, дать JTextFields DocumentListener, который проверяет содержимое при каждом изменении документа и который позволяет только отправлять Нажмите кнопку, когда все входные данные верны.

Или у вас может быть переменная int counter, массив String и один JTextField, и каждый раз, когда пользователь отправляет текст, увеличивает счетчик и помещает String в соответствующую позицию. в массиве (или ArrayList) ...

В этой ситуации Кроме того, у вас, вероятно, есть класс вопросов, не относящийся к GUI, который содержит текст одного вопроса и его ответ. Затем вы должны создать List<Question> questions = new ArrayList <> (); `и затем использовать поле index int, которое я описал выше, в ActionListener, принять ввод, а затем перейти к отображению следующего вопроса и снова отобразить его. полностью избавиться от l oop.

Самое главное, что вам нужно выйти из режима линейного программирования и войти в управляемое событиями мышление.


Например:

В следующей программе я отслеживаю вопрос, который задаю, с помощью поля состояния int, которое называется index. В ActionListener я проверяю, верен ли ответ, затем я продвигаю поле индекса с помощью index++. Затем я проверяю, осталось ли еще вопрос, сравнивая индекс со свойством size() списка массива вопросов, .....

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;
    }
}
...