【问题标题】:I'm having issues with CardLayout and one of the JPanels not receiving Keyboard events我遇到了 CardLayout 问题,其中一个 JPanel 没有收到键盘事件
【发布时间】:2021-11-01 14:49:24
【问题描述】:

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

编辑:如果你想查看整个项目(它是一个eclipse项目),这里是下载它的链接Eclipse project,老实说我不能格式化近1000行代码在 StackOverflow 上,即使对你来说也会很痛苦。

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

这是欢迎/菜单面板(其中的某些部分)。 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 只是卡在一个像鱼一样张开和合上嘴。

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;
        }
    }
}

【问题讨论】:

  • “我只提供代码的相关部分,因为它相当大。” 当人们发现问题的答案时,他们通常也会发现它不在他们认为相关的代码部分。 Edit 发布minimal reproducible example。然后我们可以确定包含相关代码。在此基础上投票结束,但请注意,标题表明这应该是两个独立的问题(有两个独立的 MRE)。
  • @AndrewThompson,我能做的最好的就是发送整个项目的链接。正如我已经提到的,游戏在没有面板切换功能的情况下也能运行,当我添加新功能时它就失败了。这就是为什么我只包括与面板切换相关的部分。
  • “这就是为什么我只包括与面板切换相关的部分。” 我将扩展我对“相关性”的进一步评论。解决方案与您相关吗?那很重要么?我问是因为我自己(和其他人)不会仔细查看代码,直到它在我们自己的 IDE 中,编译, 格式化为我们通常的期望,并且已经运行一次以证明它显示了问题.但问题是,这仅与您相关。对于我们其他人来说,这纯粹是学术性的。因此,如果无法为制定 MRE 而烦恼,那么我们为什么要为提供帮助而烦恼呢?
  • 如果你能做的最好的事情是“发送整个项目的链接”而不是付出必要的努力来制作minimal reproducible example,我能做的最好的事情就是帮助愿意这样做的其他人努力并让帮助他们更容易。
  • “看不出复制超过 1000 行代码的意义” 你真的没有注意我和 @c0der 试图交流的内容。如果你多发这样的渣滓,我会继续投反对票,投票关闭。

标签: java swing jpanel cardlayout


【解决方案1】:

问题在于使用 Key Listener,而我应该在 GameBoard JPanel 中使用 Key Binding。所以不是这个,

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多