I'm having issues with CardLayout and one of the JPanels not receiving Keyboard events

37 Views Asked by At

I will only supply the relevant parts of the code as it is quite large. Help me figure out why I never get keyboard events to the GameBoard JPanel. The game code runs just fine until I added the new feature where I wanted it to have a welcome screen.

Edit: If you would like to view the entire project (it's an eclipse project), here is the link to download it Eclipse project, I honestly can't format almost 1000 lines of code here on StackOverflow, that'll be painful even for you.

Main.java

private void initUI() throws IOException {
    cardLayout = new CardLayout();
    mainPanel = new JPanel(cardLayout);
    
    welcomeMenu = new Welcome(cardLayout, mainPanel);
    mainPanel.add(welcomeMenu, "welcome");
    game = new GameBoard();
    mainPanel.add(game, "game");

    add(mainPanel);        
    setTitle("Pacman");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(380, 420);
    setLocationRelativeTo(null);
}

This is the welcome/menu panel (some section of it). Welcome.java (servers as a menu)

@Override
public void actionPerformed(ActionEvent evt) {
    if (evt.getActionCommand() == Actions.EXIT.name()) {
        System.exit(0);
    } else if (evt.getActionCommand() == Actions.CONFIG.name()) {
        JOptionPane.showMessageDialog(null, "Not yet implemented");
    } else if (evt.getActionCommand() == Actions.PLAY.name()) {
        // The part that switches to game, works as expected.
        cl.show(mp, "game");
    }
}

GameBoard class has a KeyAdapter class within it that is used to listen to key events, however, in the addition of the new feature using CardLayout, I could not get the key events to the panel so my PacMan is just stuck in one place opening and closing its mouth like a fish.

GameBoard.java

private void initBoard() {

    addKeyListener(new TAdapter());

    setFocusable(true);

    setBackground(Color.black);

    initGame();
}
...
class TAdapter extends KeyAdapter {
    
    @Override
    public void keyPressed(KeyEvent e) {

        int key = e.getKeyCode();

        if (inGame) {
            if (key == KeyEvent.VK_LEFT) {
                req_dx = -1;
                req_dy = 0;
            } else if (key == KeyEvent.VK_RIGHT) {
                req_dx = 1;
                req_dy = 0;
            } else if (key == KeyEvent.VK_UP) {
                req_dx = 0;
                req_dy = -1;
            } else if (key == KeyEvent.VK_DOWN) {
                req_dx = 0;
                req_dy = 1;
            } else if (key == KeyEvent.VK_ESCAPE && timer.isRunning()) {
                inGame = false;
            } else if (key == KeyEvent.VK_PAUSE) {
                if (timer.isRunning()) {
                    timer.stop();
                } else {
                    timer.start();
                }
            }
        } /*
             * else { if (key == 's' || key == 'S') { inGame = true; initGame(); } }
             */
    }

    @Override
    public void keyReleased(KeyEvent e) {

        int key = e.getKeyCode();

        if (key == Event.LEFT || key == Event.RIGHT || key == Event.UP || key == Event.DOWN) {
            req_dx = 0;
            req_dy = 0;
        }
    }
}
1

There are 1 best solutions below

0
Dev Yego On

The issue was using Key Listener when I should have been using Key Binding in the GameBoard JPanel. So instead of this,

class TAdapter extends KeyAdapter {

@Override
public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    if (inGame) {
        ...
        } else if (key == KeyEvent.VK_UP) {
            req_dx = 0;
            req_dy = -1;
        } else if (key == KeyEvent.VK_DOWN) {
            ...
        }
    }
}

I replaced it with this approach (I will only demonstrate Arrow Up scenario),

private class UpAction extends AbstractAction {

    private static final long serialVersionUID = 1L;

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!inGame)
            return;

        req_dx = 0;
        req_dy = -1;
    }
}

...

private void setupKeyListeners() {
    getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "doUp");
    ...

    getActionMap().put("doUp", new UpAction());
    ...
}

And later on,

private void initBoard() {

    setupListeners();
    setFocusable(true);
    setBackground(Color.black);
    initGame();
}