Ending a timer using keyadapters?



So, I am creating this reaction time game that shows a blue ball and once you see that blue ball, you press up arrow key to get your reaction time once it turned blue. However, I am having trouble in creating a timer. I want the timer to start once the ball actually turns blue and want that timer to end once the user presses up arrow.’

Here’s an image of what I want the game to look like before the ball turns blue

and this is what I want it to look like after it turns blue, with the reaction time

here is my code. As of right now, everything works fine its just the timer part I need help with. I want to create a timer as soon as the ball turns blue and want that timer to end once the user presses up arrow but I just dont know how…

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


public class Game extends JPanel implements KeyListener
{

private JLabel start, main, time;
private ImageIcon constant, react;

final int width = 600;
final int height = 600;

private Timer replace;


private Random random;
private int randTime;

private long startTime;
private long stopTime;
private long reactionTime;

public Game()
{
  addKeyListener(this);
  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

setPreferredSize(new Dimension(width, height));
setBackground(Color.black);

start = new JLabel("Click Up Arrow when you see a blue ball");
start.setForeground(Color.white);
start.setAlignmentX(Component.CENTER_ALIGNMENT);
add(start);
 
constant = new ImageIcon("constantCircle.png");
main = new JLabel(constant);
main.setAlignmentX(Component.CENTER_ALIGNMENT);


randomTime();
replace = new Timer(randTime, timeListener);
replace.setRepeats(false);
replace.start();

timeTracker();
reactionTime = stopTime - startTime;
time = new JLabel("" + reactionTime);

add(time);
add(main);

}


public void randomTime()
{
  random = new Random();
  int max = 8000;
  randTime = random.nextInt(max);

}


ActionListener timeListener = new ActionListener()
{
  public void actionPerformed (ActionEvent e)
  {
    react = new ImageIcon("reactCircle.png");
    main.setIcon(react);
  
  }
};

public void timeTracker()
{
 if (replace.isRunning())
 {
   startTime = System.currentTimeMillis();
 }

}

public void keyPressed (KeyEvent e)
{  
  int key = e.getKeyCode();

  if (key == KeyEvent.VK_SPACE)
  {
    stopTime = System.currentTimeMillis();      
  }

}

public void keyReleased(KeyEvent e)
{
}

public void keyTyped (KeyEvent e)
{
}

}

Answer

There is no need for a Timer. A Timer is used to generate an event at a specified time interval. You don’t know when the user will react so you can’t use a Timer.

In your case all you need to do is:

  1. set your “startTime” variable to the current time when the blue ball icon is set.

  2. then you need to set the “stopTime” variable when the “Up” key is pressed. At this time you would then calculate your “reactionTime”.

The issue is that your KeyListener doesn’t work, because a KeyEvent is only dispatched to the component with focus and by default a JPanel doesn’t have focus.

The solution is to use Key Bindings, not a KeyListener. A Key Binding can be configured to receive the KeyEvent even when the panel doesn’t have focus.

Read the section from the Swing tutorial on How to Use Key Bindings for more information. There are also plenty of example on this site that use key bindings.



Source: stackoverflow