首页 > 解决方案 > 我遇到了 CardLayout 问题,其中一个 JPanel 没有收到键盘事件

问题描述

我只会提供代码的相关部分,因为它非常大。帮助我弄清楚为什么我从来没有在 GameBoard JPanel 上收到键盘事件。游戏代码运行得很好,直到我添加了我希望它有一个欢迎屏幕的新功能。

编辑:如果您想查看整个项目(它是一个 Eclipse 项目),这里是下载它的链接Eclipse 项目,老实说,我无法在 StackOverflow 上格式化近 1000 行代码,即使对于你。

主.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);
}

这是欢迎/菜单面板(其中的某些部分)。Welcome.java(作为菜单的服务器)

@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 类中有一个 KeyAdapter 类,用于监听关键事件,但是,在使用 CardLayout 添加新功能时,我无法将关键事件发送到面板,所以我的 PacMan 只是卡在一个地方打开和像鱼一样闭上嘴。

游戏板.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;
        }
    }
}

标签: javaswingjpanelcardlayout

解决方案


当我应该在GameBoard JPanel中使用Key Binding时,问题是使用Key Listener 。所以代替这个,

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) {
            ...
        }
    }
}

我用这种方法替换了它(我只会演示 Arrow Up 场景),

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());
    ...
}

而后来,

private void initBoard() {

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

推荐阅读