简体   繁体   中英

For Loop not waiting for User Response in JTextField

Seeking help again to figure out something for a homework assignment. I've got most of this down, but I'm having a really hard time understanding why I can't make the for-loop wait for user text entry. Basically, I need the program to prompt a user to enter a color from memorization. The colors are contained in an array as strings. On each iteration of the for-loop, I'd like the action listener to check and see if the proper text is entered. If so, the box should change it's JLabel text from "Enter color number x" to "Enter color number x+1"

Here's what I've noticed: My for loop runs through it's entire iteration cycle before even considering to let the user type text into the field. So instead of prompting the user for color number 1, it just goes strait to color number 5.

Here's the code I've got for it:

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

public class ColorGame extends JFrame
{
  private static final int WIDTH = 300;
  private static final int HEIGHT = 200;
  //Text field that will confirm a user submission
  private JTextField colorEntry = new JTextField(10);  
  private int colorIndex = 0; //current index of colorSequence
  //String Array of colors to be searched for and validated in a text field
  private String[] colorSequence = {"red", "white", "yellow", "green", "blue"};

  public ColorGame()
  {
    setTitle("Memory Game");
    setSize(WIDTH, HEIGHT);
    setLayout(new FlowLayout());
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    createContents();
    setVisible(true);
  }

  public void createContents()
  {
    //dialog box to inform user of program's purpose
    JOptionPane.showMessageDialog(null, "How good is your memory?\nTry to memorize "
        + "this color sequence:\n\nred, white, yellow, green, blue"); 
    //JLabel to prompt user for color
    JLabel colorPrompt = new JLabel();

    add(colorPrompt);
    add(colorEntry);

    for(int i = 0; i < colorSequence.length; i++)
    {
      colorIndex = i + 1;
      colorPrompt.setText("Enter color number " + colorIndex + ":");
      colorEntry.addActionListener(new Listener());  
    }
  }

  private class Listener implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {
      String colorText = "";

      colorText = colorEntry.getText();
      if(colorText.equals(colorSequence))
        System.out.println("Hello");
      else
        System.out.println("No");

    }
  }

  public static void main(String[] args)
  {
    new ColorGame();
  }
}

Your for loop is code for a line-by-line run command-line program, but that's not how event driven GUI's work.

Instead, you want code in the ActionListener to advance a counter and change behavior based on that counter.

private class Listener implements ActionListener
{

  int counter = 0;
  public void actionPerformed(ActionEvent e)
  {
    switch (count) {
      case 0:
        // do something for 0
        // including changing JLabel text if need be
        break;            
      case 1:
        // do something for 1
        break;
      case 2:
        // do something for 2
        break;
      default;
        // do something for default
    }
    count++;

  }
}

A for loop will loop immediately with no concern for a user's input or for when a button has been pressed. The key is that you want to alter your program's state depending on how many times a JButton has been pressed. And because the state change is triggered by the button press, there's no need to worry about some loop looping too fast.


Here's a related example that is not an exact solution, but should give you some ideas towards your solution:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;    
import javax.swing.*;

public class ChangeState {

   public static final String[] STRINGS = {
      "Enter the 1st String:",
      "Enter the 2nd String:",
      "Enter the 3rd String:"
   };

   private static void createAndShowGui() {
      final JTextField textField = new JTextField(10);
      final String[] replies = new String[STRINGS.length];
      final JLabel label = new JLabel(STRINGS[0]);
      JPanel mainPanel = new JPanel();
      mainPanel.add(label);
      mainPanel.add(textField);

      textField.addActionListener(new ActionListener() {
         int count = 0;
         @Override
         public void actionPerformed(ActionEvent arg0) {
            if (count < STRINGS.length) {
               replies[count] = textField.getText();
               count++;
               if (count < STRINGS.length) {
                  label.setText(STRINGS[count]);
               } else {
                  label.setText("Done!");
                  System.out.println("Replies:");
                  for (String reply : replies) {
                     System.out.println(reply);
                  }
               }
               textField.setText("");
            } 
         }
      });

      JFrame frame = new JFrame("ChangeState");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

Basically, I ended up figuring out that I don't need to repeat my actions in createContents() and that my actions get repeated through the listener. Your comment about event driven programming is what helped me with that.

private class Listener implements ActionListener   
{
  //counter to dynamically change numeric text values 
  //as well as to mark progress through colorSequence
  int count = 1; 
  public void actionPerformed(ActionEvent e)
  {
    if (count < colorSequence.length)
    {
      if (colorEntry.getText().equals(colorSequence[count - 1]))
      {
        count++;
        colorEntry.setText("");
        colorPrompt.setText("Enter color number: " + count);
      }
      else
      {
        colorEntry.setVisible(false);
        colorPrompt.setText("Sorry - wrong answer. Eat more antioxidants.");
      }
    } //end if (for while the program is still iterating through the array)
    else
    {
      colorPrompt.setText("Congratulations - your memory is perfect");
      colorEntry.setVisible(false);
    } //end else (the user has properly stepped through all the colors in the array)
  } //end actionPerformed   
} //end private class Listener

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