繁体   English   中英

Java Swing:输入错误时如何允许用户再次输入Jtextfield?

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

我正在做一个数学问答游戏,其中问题是随机生成的,用户必须在 jtextfield 中填写答案 然后,当用户按下回车键检查答案时,下一个问题也将以相同的形式(显示在 jlabel 中)加载10 轮

但是我遇到了一个问题,我正在使用 for 循环(继续生成问题并提示用户回答 10 轮)它不允许用户在第一个问题之后在文本字段中输入答案。 它跳过 jtextfield 中的 gettext() 并在文本字段留空时重复空文本字段消息。 当输入除数字以外的其他输入时,重复的 catch 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;
}

这不是事件驱动程序的工作方式,您要做的是将线性控制台编程硬塞到事件驱动的 GUI 中。 该循环实际上阻塞了 Swing 事件线程(“事件调度线程或 EDT”),这会使您的程序冻结且无用。

相反,让您的程序更加事件驱动和更加“有状态”,它会根据关键“状态”字段/变量的 state 更改它对事件的响应方式。

在这种情况下,您可以向用户提供 10 个 JTextField 并要求他们在字段中输入数据,并且在所有字段都填充了适当的数据之前不允许进一步的操作——例如,有一个禁用的“提交”JButton,给JTextFields 是一个 DocumentListener,它可以在文档更改时检查内容,并且只有在所有输入都有效时才启用提交按钮。

或者您可以有一个 int 计数器变量、一个字符串数组和一个 JTextField,并且每次用户提交文本时,递增计数器并将字符串放入数组(或 ArrayList)中的适当 position 中...

在这种情况下,您可能会有一个非 GUI 问题 class,它包含一个问题文本及其答案。 然后,您将创建一个List<Question> questions = new ArrayList<>();`,然后在 ActionListener 中使用我上面描述的 index int 字段,接受输入,然后继续显示下一个问题并显示它,再次完全摆脱 for 循环。

但最重要的是,您需要离开线性编程模式并进入事件驱动的思维模式。


例如:

在下面的程序中,我使用名为index的 int state 字段来跟踪我要问的问题。 在 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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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