Java Swing。如何让用户在输入错误时再次输入Jtextfield?

问题描述 投票:-1回答:1

我在做一个 数学测验游戏 其中,问题是随机产生的,用户必须要有 在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;
}
java swing
1个回答
1
投票

这不是事件驱动程序的工作方式,你要做的是把线性控制台编程塞进事件驱动的GUI中。循环实际上是阻塞了Swing事件线程("事件派遣线程或EDT),这可能会使你的程序冻结和无用。

相反,让你的程序更多的是事件驱动,更多的是 "有状态的",它根据关键的 "状态 "字段variables的状态来改变它对事件的响应。

在这种情况下,你可以给用户提供10个JTextFields,并要求他们在这些字段中输入数据,直到所有字段都填满了适当的数据才允许进一步的操作--例如,有一个 "提交 "的JB按钮是被禁用的,给JTextFields提供一个DocumentListener,它可以在文档发生变化时随时检查内容,只有当所有的输入都是有效的时候才启用提交按钮。

或者你可以有一个int计数器变量,一个String数组和一个JTextField,每次用户提交文本时,递增计数器并将String放到数组(或ArrayList)的适当位置......。

在这种情况下,你可能会有一个非GUI的Question类,其中包含一个单一的问题文本和它的答案。然后你会创建一个 List<Question> questions = new ArrayList<>();`然后利用我上面说的index int字段,在ActionListener中,接受输入,然后前进显示下一个问题并显示,同样完全摆脱for循环。

不过最重要的是,你需要离开线性编程模式,进入事件驱动的思路。


举个例子

在下面的程序中,我用一个叫 "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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.