简单游戏中的CardLayout不能正确切换JPanel

时间:2017-04-23 11:28:01

标签: java swing cardlayout

我正在为我的学习制作游戏'Breakout'的重新制作版本,并面临一个奇怪的问题:

我有一个简单的开始屏幕,玩家应该可以输入名称并查看当前的高分等。要开始游戏,我使用CardLayout,它应切换到gamePanel。不知怎的,这不会发生,但游戏循环开始了,当球离开JPanel时,我得到游戏结束消息。奇怪的是,gamePanel与游戏Over JOptionPane一起出现,切换回开始屏幕正常工作。我在StackOverflow上也搜索了很多,但我发现的解决方案都没有对我有用。这是我的代码:

这是我的Game.java,主要方法位于:

public class Game  extends JFrame {
    private static final int width = 1280;
    private static final int height = 720;
    private static final String LOBBY_PANEL = "Lobby Panel";
    private static final String GAME_PANEL = "Game Panel";
    private boolean run = false;
    private CardLayout cardLayout;
    private JPanel cardPanel = new JPanel();
    private LobbyPanel lobbyPanel;
    private GamePanel gamePanel;

    public Game(){
        super("Breakout Remastered");
        cardPanel.setLayout(new CardLayout());
        cardLayout = (CardLayout) cardPanel.getLayout();
        lobbyPanel = new LobbyPanel(this);
        gamePanel = new GamePanel(this);
        cardPanel.add(lobbyPanel, LOBBY_PANEL);
        cardPanel.add(gamePanel, GAME_PANEL);
        this.add(cardPanel);
        this.pack();
        this.setSize(width, height);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        cardLayout.show(cardPanel, LOBBY_PANEL);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Game gameFrame = new Game();
            gameFrame.setVisible(true);
        });

    }

    public void playGame() {
        cardLayout.show(cardPanel, GAME_PANEL);
        this.validate();
        this.repaint();
        this.run = true;

        while (run) {
            gamePanel.move();
            gamePanel.repaint();
            try {
                Thread.sleep(10);
            } catch (InterruptedException iEx) {
                iEx.printStackTrace();
            }
        }
    }

    public void stopGame() {
        cardLayout.show(cardPanel, LOBBY_PANEL);
        this.run = false;
    }
}

这是我的GamePanel.java:

public class GamePanel extends JPanel {
    private Game game;
    private Ball ball = new Ball(this);
    private Racquet racquet = new Racquet(this);

    public GamePanel(Game game) {
        this.game = game;
        KeyListener keyListener = new KeyListener() {
            @Override
            public void keyTyped(KeyEvent keyEvent) {

            }

            @Override
            public void keyPressed(KeyEvent keyEvent) {
                racquet.keyPressed(keyEvent);
            }

            @Override
            public void keyReleased(KeyEvent keyEvent) {
                racquet.keyReleased(keyEvent);
            }
        };
        addKeyListener(keyListener);
        setFocusable(true);
    }

    public void move() {
        ball.move();
        racquet.move();
    }

    public void reset() {

    }

    @Override
    public void paint(Graphics graphics) {
        super.paint(graphics);
        Graphics2D g2d = (Graphics2D) graphics;
        g2d.setColor(Color.BLACK);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        ball.paint(g2d);
        racquet.paint(g2d);
    }

    public void gameOver() {
        JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
        game.stopGame();
    }


    public Racquet getRacquet() {
        return racquet;
    }

    public void setRacquet(Racquet racquet) {
         this.racquet = racquet;
    }
}

这是我的LobbyPanel.java:

public class LobbyPanel extends JPanel implements ActionListener {

    private static final JLabel labelForUserTextField = new JLabel("Username");
    private JTextField userName = new JTextField("", 20);
    private JButton startButton = new JButton("Play!");
    private JButton highScoreButton = new JButton("View Best");
    private JButton cancelButton = new JButton("Cancel");
    private Game game;

    public LobbyPanel(Game game) {

        startButton.addActionListener(this);

        this.game = game;
        this.setLayout(new GridBagLayout());
        this.setBorder(new EmptyBorder(10, 10, 10, 10));
        GridBagConstraints labelConst = new GridBagConstraints();
        labelConst.insets = new Insets(3, 3, 3, 3);

        labelConst.gridx = 0;
        labelConst.gridy = 0;
        this.add(labelForUserTextField, labelConst);
        labelConst.gridx = 1;
        this.add(userName, labelConst);
        labelConst.gridx = 0;
        labelConst.gridy = 1;
        this.add(cancelButton, labelConst);
        labelConst.gridx = 1;
        this.add(highScoreButton, labelConst);
        labelConst.gridx = 2;
        this.add(startButton, labelConst);

    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        try {
            if(actionEvent.getSource() == this.startButton) {
                this.game.playGame();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

我希望有人能够弄清楚为什么这段代码不能按预期工作。 提前谢谢!

1 个答案:

答案 0 :(得分:0)

发现问题是Frakcool所提到的:while(true){...阻止了GUI,所以我用一个Thread替换它,现在它可以工作了。