如何从JPanel开始Canvas游戏?

时间:2016-11-06 09:02:18

标签: java swing

我将游戏写成大学项目。它使用JCanvas来显示游戏并且该部分完全正常工作,但我想添加一个菜单,您可以在其中选择" play" "高分" "出口"等。

我有一个包含JCanvas和JPanel的JFrame(后者是菜单)。但是,如果我从面板开始游戏,框架会冻结 我运行了一些测试,问题是当从JPanels actionListener调用playGame()方法时,画布无法更新,直到该方法返回。

以下是相关部分:

public class Main {

public static Game game = new Game();
private static JFrame mainFrame = new JFrame("Snake");
private static MenuPanel menuPanel = new MenuPanel();

public static void main(String[] args) {
    mainFrame.setLayout(new BorderLayout());

    mainFrame.add(menuPanel, BorderLayout.SOUTH);
    mainFrame.pack();
    mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    mainFrame.setVisible(true);

}

static void playGame(){
    mainFrame.setVisible(false);
    mainFrame.remove(menuPanel);
    menuPanel.setEnabled(false);

    ScoreboardPanel scoreboardPanel = new ScoreboardPanel();
    mainFrame.add(scoreboardPanel, BorderLayout.NORTH);

    game.addPanel(scoreboardPanel);
    mainFrame.add(game, BorderLayout.CENTER);
    mainFrame.pack();
    mainFrame.setVisible(true);

    // ANYTHING here stops the frame's rendering until playGame() returns (like game.play() or sleep(x)
}

}

public class MenuPanel extends JPanel {

private class MenuActionListener implements ActionListener {
    public void actionPerformed(ActionEvent actionEvent){
        switch (actionEvent.getActionCommand()){
            case "play":
                // TODO This somehow breaks everything. The game loop runs but the window freezes.
                Main.playGame();
                break;
            case "highscore":
                break;
            case "leveleditor":
                break;
            case "exit":
                System.exit(0);
                break;
        }
    }
}

如果有更多帮助,可以使用完整的代码:https://github.com/nodar86/prog3-snake

2 个答案:

答案 0 :(得分:2)

重绘和事件发送均在The Event Dispatch Thread(EDT)上执行。从事件监听器调用Game.play方法并使用sleep阻止EDT,因此Swing没有机会重新绘制您的帧。

解决此问题的最简单方法 - 使用javax.swing.Timer替换Game.play中的手工制作计时器。在计时器的每个滴答声中,您应该在游戏的时间点模拟。这将允许Swing根据需要重新绘制。如果您事先准备好计时器,您的菜单听众可以启动和停止它。

附注:可能,值得您使用special menu components菜单。

答案 1 :(得分:2)

你没有使用" JCanvas"没有" JCanvas"除非你自己制作了#34; Canvas" (in here your Game class extends Canvas.)我建议您更新游戏,以便不再在同一个GUI中混合使用轻量级和重量级工具包。但看起来你几乎已经完成了,所以试试kgeorgiy的答案。