0

I have some problem with my code. I want to implement a keylistener. I have a keyHandler class which takes care about keyinput and a while loop in the main class to check if a certain key is pressed or not. I dont understand the behavior of my code. the strange thing is that every thing works when I put the System.out.println("hello") command in front of my if statement. but when i comment it out my programm doesnt realize that i press the key Im checkin in my if statement. I think i could find a workaround. but i would be very glad to understand this strange behavior. why is this happening. Sorry for my bad english. I hope you guys can help me.

public static void main(String[] args) {
    boolean running = true;
    JFrame window;
    KeyHandler k = new KeyHandler();
    
    window = new JFrame();
    window.setVisible(true);
    window.addKeyListener(k);
    
    while (running) {
        //System.out.println("hello");
        if (k.isKeyPressed(KeyEvent.VK_W)) {
            System.out.println("--------------------------------------------------------------------------");
        }
    }
}

//here is the KeyHandler class

public class KeyHandler implements KeyListener {

private boolean[] keysPressed = new boolean[128];

@Override
public void keyTyped(KeyEvent e) {
    
}

@Override
public void keyPressed(KeyEvent e) {
    keysPressed[e.getKeyCode()] = true;
    System.out.println(e.getKeyChar());
    System.out.println(keysPressed[e.getKeyCode()]);
    
}

@Override
public void keyReleased(KeyEvent e) {
    keysPressed[e.getKeyCode()] = false;
    System.out.println(e.getKeyChar());
    System.out.println(keysPressed[e.getKeyCode()]);
}

public boolean isKeyPressed(int keyCode) {
    return keysPressed[keyCode];
}
}
Zac
  • 2,180
  • 2
  • 23
  • 36
  • 1
    Why do you want to use a `while` loop to check whether a key is pressed instead of using your `KeyListener` to react to keypresses? – jsheeran Mar 22 '22 at 15:20
  • in a modern gui framework i couldn't understand why you still need spin loops to get key board events. – Lei Yang Mar 22 '22 at 15:30
  • Because I only want to ask the keyhandler if the key is pressed and the reaction else where. Do you think the while loop is too fast ans overloads the system? i cant imagine why the print command changes the way the programm is reacting. – philmik93abc Mar 22 '22 at 15:35
  • 1
    Tight spin loops destroy apps and they're unnecessary for (what's essentially an) interrupt handlers. Key listeners *already* separate keypress events from what happens on the event. – Dave Newton Mar 22 '22 at 16:18
  • Thomas Kläger, I think this is it. Since Swing uses the Event Dispatch Thread I think the problem is that my if statement does not see the changes made in that thread. I tryed out implementing a delay instead of the print statement. when the delay is long enough it has the same effect like the print statement. So I guess that the threads are not synchronised – philmik93abc Mar 22 '22 at 17:25

2 Answers2

1

The whole purpose of events and event handling is you don't need a loop to listen for events. Simply start your UI, add the listeners to a list, and allow the listeners to handle the processing.

Create a listener

public interface MyListener extends EventListener {
    public void doSomething();
}

Now use it. With this code it just spits out some text when W is pressed, but the listeners could be another component or anything that uses the interface. No need for extra loops.

public class Main {
private EventListenerList listenerList = new EventListenerList();
public Main() {
    JFrame frame = new JFrame();
    addListener(new MyListener() {
        @Override
        public void doSomething() {
            System.out.println("Hello 1");
        }
    });
    addListener(new MyListener() {
        @Override
        public void doSomething() {
            System.out.println("Hello 2");
        }
    });
    
    frame.addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_W) {
                fireMyEvent();
            }
        }
    });
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

public void addListener(MyListener listener) {
    listenerList.add(MyListener.class, listener);
}

private void fireMyEvent() {
    MyListener[] listeners = listenerList.getListeners(MyListener.class);
    if (listeners == null) {
        return;
    }
    for (MyListener listener : listeners) {
        listener.doSomething();
    }
}

public static void main(String [] args) {
    new Main();
}
}
Ryan
  • 1,762
  • 6
  • 11
0

Here's a link that might help. I would not check for a key being pressed by that method. You are creating a resource hog, first off: by having

boolean running = true;

you then enter a while loop,

while (running) {
  do x;
}

this can create a spin lock on some systems, this is a very bad practice. As user Lei Yang stated it is really not needed especially with the classes we have today and modern GUI's, your creating an endless loop. One this most certainly is a way to slow down a system, two you really can't continue coding past that point as you have no way to exit the loop. Some IDE's also have a check that won't allow your application to start if you have a loop that is infinite, almost all will at least give you a warning. you should at least if you are looking for a certain key and have to implement it that way do:

    while (running) {
        //System.out.println("hello");
        if (k.isKeyPressed(KeyEvent.VK_W) = "e") {
            running = false;
        }
    }

at least that won't be an endless loop.