Reputation: 557
I'm having simple KeyHandler
public class KeyHandler implements KeyListener {
private final Set<Integer> keyEvents = new LinkedHashSet<>();
public Set<Integer> pressedKeys() {
return keyEvents;
}
@Override
public void keyPressed(KeyEvent e) {
keyEvents.add(e.getKeyCode());
}
@Override
public void keyReleased(KeyEvent e) {
keyEvents.remove(e.getKeyCode());
}
@Override
public void keyTyped(KeyEvent e) {
}
}
Which is added to JFrame
frame.addKeyListener(keyListener);
Rest is probably irrevelant, but I'm passing same instance to KeyBinder
public class KeyBinder {
private final Map<Integer, GameEvent> bindings = new HashMap<>();
private final KeyHandler keyHandler;
public KeyBinder(KeyHandler keyHandler) {
this.keyHandler = keyHandler;
bindings.put(KeyEvent.VK_A, MoveEvent.MOVE_LEFT);
bindings.put(KeyEvent.VK_D, MoveEvent.MOVE_RIGHT);
bindings.put(KeyEvent.VK_S, MoveEvent.MOVE_DOWN);
bindings.put(KeyEvent.VK_W, MoveEvent.MOVE_UP);
}
public List<GameEvent> mapEvents() {
final var events = new ArrayList<GameEvent>();
keyHandler.pressedKeys().forEach(key -> events.add(bindings.get(key)));
return events;
}
}
And then, I'm passing those GameEvents
into Player
instance to make him move
@Override
public void update(java.util.List<GameEvent> events) {
events.forEach(this::handleEvent);
}
private void handleEvent(GameEvent event) {
if (event instanceof MoveEvent) {
updatePosition((MoveEvent) event);
}
}
private void updatePosition(MoveEvent event) {
switch (event) {
case MOVE_UP -> position = new Position(position.getX(), position.getY() - speed);
case MOVE_DOWN -> position = new Position(position.getX(), position.getY() + speed);
case MOVE_RIGHT -> position = new Position(position.getX() + speed, position.getY());
case MOVE_LEFT -> position = new Position(position.getX() - speed, position.getY());
}
}
It works perfectly fine if I'm running single instance of my application. But since, that is intend to be online game, I want to run 2 instances at same time for test purposes. Unfortunatelly, one I start second instance, my KeyHandler
isn't working anymore in any of them, it just dont record any KeyEvents
. I know my application is stil running because my server application keeps on receiving data from both clients.
I just realized that something else is an issue. KeyHandler
stops working once I click canvas... I dont even need second instance of my application. Here is the code of JFrame
and Canvas
I'm using to draw things...
public class Display {
private JFrame frame;
private Canvas canvas;
public Display(KeyListener keyListener) {
initFrame(keyListener);
initCanvas();
frame.add(canvas);
frame.pack();
}
private void initFrame(KeyListener keyListener) {
frame = new JFrame(GameConfig.TITLE);
frame.setSize(GameConfig.SCREEN_WIDTH, GameConfig.SCREEN_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addKeyListener(keyListener);
}
private void initCanvas() {
canvas = new Canvas();
canvas.setPreferredSize(new Dimension(GameConfig.SCREEN_WIDTH, GameConfig.SCREEN_HEIGHT));
canvas.setMaximumSize(new Dimension(GameConfig.SCREEN_WIDTH, GameConfig.SCREEN_HEIGHT));
canvas.setMinimumSize(new Dimension(GameConfig.SCREEN_WIDTH, GameConfig.SCREEN_HEIGHT));
}
public Canvas getCanvas() {
return canvas;
}
}
Upvotes: 0
Views: 241
Reputation: 642
The reason your keylistener isn't listening to any keyevents is because KeyListeners only work when the component has focus. It seems like when you click on the canvas, the canvas is now the owner of the focus, therefore the frame isn't focused anymore.
Generally, I'd suggest using Key Bindings for this. Key bindings can listen to keyevents even when your component isn't focused. But if you want to keep using KeyListeners, here are two solutions:
Add a FocusListener to the frame.
frame.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {}
public void focusLost(FocusEvent e) {frame.requestFocus();}
});
Disable the focusability of canvas.
canvas.setFocusable(false);
These solutions are not recommended, but it should do the job for your case.
Upvotes: 3