交换JPanel,第二个JPanel不显示

时间:2015-04-02 19:59:05

标签: java dynamic jframe jpanel swap

我有一个JFrame和2个JPanel。一个面板是带按钮的开始屏幕。另一个面板是游戏画面。当我删除开始屏幕并显示游戏屏幕时,JFrame没有任何反应。开始屏幕是持久的但不可用,游戏在后台运行而不更新屏幕。当游戏完成时,开始屏幕再次可用。我在网上到处寻找解决方案。他们都说removeAll,revalidate,repaint,pack或getContentPane.removeAll。我还没有能够使用这些解决方案。这是驱动程序类:

public class BallDriver extends JFrame {

    private static final long serialVersionUID = 1L;

    int width = 500;
    int height = 500;

    Container cont;
    StartScreen start;  
    BallGame ballGame;

    public BallDriver() {
        cont = getContentPane();
        startScreen();  
    }

    private void startScreen() {

        setTitle("BallGame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(width, height));
        setPreferredSize(new Dimension(500,500));

        start = new StartScreen();
        JButton[] startButtons = start.getButtons();
        setupButtons(startButtons);
        add(start, BorderLayout.CENTER);        
    }

    private void startGame(String difficulty) throws InterruptedException {
        removeAll();
        setSize(new Dimension(width, height));
        setPreferredSize(new Dimension(width, height));

        ballGame = new BallGame(width, height);
        ballGame.setPreferredSize(new Dimension(width, height));
        add(ballGame, BorderLayout.CENTER);
        revalidate();
        repaint();

        while(!ballGame.endGame()) {
            ballGame.moveBall();
            ballGame.repaint();
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) { e.printStackTrace(); }
        }   

        removeAll();
        add(start, BorderLayout.CENTER);
        revalidate();
        repaint();
    }   

    private void setupButtons(final JButton[] buttons) {
        for (JButton button : buttons) {
            button.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    Object object = e.getSource();
                    try {
                        if (object == buttons[0])                       
                            startGame(StartScreen.MODE_EASY);
                        if (object == buttons[1])
                            startGame(StartScreen.MODE_NORMAL);
                        if (object == buttons[2])
                            startGame(StartScreen.MODE_HARD);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
            });
        }
    }

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                  BallDriver ballDriver = new BallDriver();
                  ballDriver.setVisible(true);
            }
        });
    }       
}

编辑: 我已经更新了类以使用cardlayout,但同样的事情发生了。

public class BallDriver extends JFrame {

    private static final long serialVersionUID = 1L;

    int width = 500;
    int height = 500;

    JPanel cardPanel = new JPanel();
    Container cont;
    StartScreen start;  
    BallGame ballGame;
    CardLayout cardLayout = new CardLayout();

    public BallDriver() {
        setTitle("BallGame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(new Dimension(width, height));
        setPreferredSize(new Dimension(width, height));

        cardPanel.setLayout(cardLayout);
        cont = getContentPane();
        add(cardPanel, BorderLayout.CENTER);
        startScreen();

    }

    private void startScreen() {
        start = new StartScreen();
        JButton[] startButtons = start.getButtons();
        setupButtons(startButtons);
        cardPanel.add(start, "start");      
        cardLayout.show(cardPanel, "start");
    }

    private void startGame(String difficulty) throws InterruptedException {

        ballGame = new BallGame(width, height);
        cardPanel.add(ballGame, "game");
        cardLayout.show(cardPanel, "game");
        cardPanel.revalidate();
        cardPanel.repaint();

        while(!ballGame.endGame()) {
            System.out.println("Running");
            ballGame.moveBall();
            ballGame.repaint();
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) { e.printStackTrace(); }
        }
    }   

    private void setupButtons(final JButton[] buttons) {
        for (JButton button : buttons) {
            button.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    Object object = e.getSource();
                    try {
                        if (object == buttons[0])                       
                            startGame(StartScreen.MODE_EASY);
                        if (object == buttons[1])
                            startGame(StartScreen.MODE_NORMAL);
                        if (object == buttons[2])
                            startGame(StartScreen.MODE_HARD);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
            });
        }
    }

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                  BallDriver ballDriver = new BallDriver();
                  ballDriver.setVisible(true);
            }
        });
    }       
}

1 个答案:

答案 0 :(得分:2)

CardLayout允许您向Container添加多个面板,一次只显示1个面板,并且可以在面板之间切换。您将父级布局设置为CardLayout,向您的帧添加面板,指定名称作为约束:

 CardLayout layout = new CardLayout();
 JFrame frame = new JFrame();
 frame.setLayout(layout);

 JPanel panel1 = new JPanel();
 JPanel panel2 = new JPanel();

 frame.add(panel1, "first");
 frame.add(panel2, "second");

添加的第一个面板是第一个显示的tk。要在面板之间切换,请调用CardLayout#show(Container, String),传递面板的父级(考虑" deck ")和所需的特定面板的名称(考虑" ")。

 layout.show(frame, "second");

人们对CardLayout的一个常见问题是让父级调整大小为当前面板的大小。这可以通过extending upon CardLayout

来实现