having problems with keyListener

1.1k Views Asked by At

i am trying to make a simple reaction test in java. when the screen turns green i press space witch is supposed to change te boolean "clicked into false and stop the loop that measures time. in reality the key listner does nothing. am i adding the keay listener to the right compnent( jpanel panel)? is there any other problems?

    import java.awt.Color;
    import java.awt.RenderingHints.Key;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;        
    import javax.swing.*;

    public class mainCheck {
    // //////////////////////////////////////
    public static void timeKeeper() {
         boolean clicked=false;
        long time = 10000;
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        panel.setBackground(Color.GREEN);
        while (time > 0 && !clicked) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            time--;
        }
        panel.setBackground(Color.gray);
        long time2= 10000-time;
        JLabel x = new JLabel("" +time2+"");
        panel.add(x);    
    }

    // //////////////////////////////////////
    static boolean clicked;
    JFrame frame;
    static JPanel panel;

    public mainCheck() {
        frame = new JFrame();
        panel = new JPanel();
        clicked = false;
        Handler handler = new Handler();
        frame.addKeyListener(handler);
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500,500);
        frame.setVisible(true);
    }
    // //////////////////////////////////////

    public static void main(String[] args) {
        mainCheck f = new mainCheck();
        panel.getActionMap();           
        f.timeKeeper();
    }

    // //////////////////////////////////////
    public class Handler implements KeyListener {

        @Override
        public void keyPressed(KeyEvent e) {
            // TODO Auto-generated method stub
        }

        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub    
        }

        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub
            if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                clicked = false;
                System.out.println("space pressed");
            }    
        }    
    }
}
3

There are 3 best solutions below

0
On
  • The problem is that you "e.getKeyCode()" always is "0" so change for "e.getKeyChar()" and "(char)32"
  • the other problem is in that you put clicked = false and must be "true"
  • And the last problem you have is in "timeKeeper()" you have to erase "boolean" because it is already declarated

    Bad
    public static void timeKeeper() {
    boolean clicked=false
    ....}
    
    Good
    public static void timeKeeper() {
    clicked=false
    ....}
    

This is the correct code:

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

public class mainCheck {
// //////////////////////////////////////
public static void timeKeeper() {
    clicked=false;
    long time = 10000;
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    panel.setBackground(Color.GREEN);
    while (time > 0 && !clicked) {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        time--;
    }
    panel.setBackground(Color.gray);
    long time2= 10000-time;
    JLabel x = new JLabel("" +time2+"");
    panel.add(x);    
}

// //////////////////////////////////////
static boolean clicked;
JFrame frame;
static JPanel panel;
Handler handler = new Handler();

public mainCheck() {
    frame = new JFrame();
    panel = new JPanel();
    clicked = false;

    frame.addKeyListener(handler);
    frame.add(panel);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(500,500);
    frame.setVisible(true);
}
// //////////////////////////////////////

public static void main(String[] args) {
    mainCheck f = new mainCheck();
    panel.getActionMap();           
    f.timeKeeper();
}

// //////////////////////////////////////
public class Handler implements KeyListener {

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub    
    }

    @Override
    public void keyTyped(KeyEvent e) {
        if (e.getKeyChar() == (char)32) {
            clicked = true;
            System.out.println("space pressed");
        }    
    }  
}
}
0
On
  • do not use Thread.sleep(5000); block Event Dispatch Thread and during sleep you can lost all events to the already visible Swing GUI

  • use Swing Timer instead

  • Thread.sleep(1); could be proper delay for space enviroment, non_human, very short period attacking latency in Native OS (8-14miliseconds, depends of Native OS)

  • JLabel x = new JLabel("" +time2+""); and panel.add(x); in AWT/Swing isn't any notifiers that some, any, part of JComponents are removed or added, have to notify used LayoutManager (JPanel has FlowLayout in API) by using methods revalidate and repaint, e.g.

.

JLabel x = new JLabel("" +time2+"");
panel.add(x);
panel.revalidate();
panel.repaint();
1
On

It's a really bad idea to use Thread.sleep() to decrement the time value. Use a Timer object instead:

public void myTimer(){
    Timer myTimer = new Timer(delay, new ActionListener(){
        public void actionPerformed(ActionEvent e){
            //Stuff to do
        }
    });
}

Where delay is the amount of time you delay the timer. You start the timer with myTimer.start();