如何将BorderLayout放入CardLayout?

时间:2014-05-26 06:32:54

标签: java swing layout-manager cardlayout border-layout

问题可能不正确,但我不知道如何正确询问。对不起,我很抱歉。

问题在于:

我的JFrame CardLayoutlayout manager。 我有三个JPanel&我在它们之间切换。一切都很好,直到我不得不将2 JPanel加入其中一个。现在我的JPanel之一应该包含另外两个JPanel&#39}。我在某处读到它是可行的。因此JPanel应该有BorderLayout。它应该如何: enter image description here

以下是我之前的事情:

  • 我的JFrame课程:

    public class JavaGame2 extends JFrame {
    
        public JavaGame2(){
    
            CardLayout layout = new CardLayout();
            setLayout(layout);
            GameController controller = new CardLayoutGameController(getContentPane(), layout);
    
            gamePanel = new GamePanel(controller);          
            menuPanel = new MenuPanel(controller);
            lvlPanel = new LvlEndPanel(controller);
    
            add(gamePanel, CardLayoutGameController.GAME_PANEL);
            add(menuPanel, CardLayoutGameController.MENU_PANEL);
            add(lvlPanel, CardLayoutGameController.LEVEL_PANEL);
    
    
            controller.showMenu();
    }
    
  • 正在切换所有CardLayoutGameController
  • JPanel

    public class CardLayoutGameController implements GameController {
        public static final String GAME_PANEL = "GamePanel";
        public static final String MENU_PANEL = "MenuPanel";
        public static final String LEVEL_PANEL = "LvlPanel";            
    
        private Container container;
        private CardLayout cardLayout;
    
        public CardLayoutGameController(Container parent, CardLayout layout) {
            container = parent;
            cardLayout =  layout;
        }
    
        @Override
        public void showMenu() {
            cardLayout.show(container, MENU_PANEL);
        }
    
        @Override
        public void showGame() {
            cardLayout.show(container, GAME_PANEL);
        }
    
        @Override
        public void showEndLvl(){
            cardLayout.show(container, LEVEL_PANEL);
        }
    }
    

然后我添加了两个JPanelInterfacePanelGameMainPanel(应该包含此InterfacePanel和我的旧GamePanel

现在的样子:

UPD 可运行的示例:

  • 可运行的课程:

    public class Mcve extends JFrame {
    
        private GamePanel gamePanel;
        private LvlEndPanel lvlPanel;
        private GameMainPanel gameMainPanel;
    
    
        Mcve(){
            CardLayout layout = new CardLayout();
    
            setLayout(layout);
            GameController controller = new CardLayoutGameController(getContentPane(), layout);
    
            gamePanel = new GamePanel(controller);  
            lvlPanel = new LvlEndPanel(controller);
            gameMainPanel = new GameMainPanel(controller,this.getContentPane());
    
            add(gamePanel, CardLayoutGameController.GAME_PANEL);
            add(lvlPanel, CardLayoutGameController.LEVEL_PANEL);
            add(gameMainPanel, CardLayoutGameController.GAME_MAIN_PANEL);
            controller.showMenu();
    
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            pack();
            setLocationRelativeTo(null);
            setTitle("JavaGame2");
            setResizable(false); 
        }
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    JFrame jgame = new Mcve();
                    jgame.setVisible(true);
                }
            });
        }
    }
    
  • GameController

    public interface GameController {
        public void showMenu();
        public void showGame();
        public void showEndLvl();
    }
    
  • CardLayoutGameController

    public class CardLayoutGameController implements GameController {
        public static final String MENU_PANEL = "MenuPanel";
        public static final String LEVEL_PANEL = "LvlPanel";
        public static final String GAME_MAIN_PANEL = "GameMainPanel";
    
        private Container container;
        private CardLayout cardLayout;   
    
        public CardLayoutGameController(Container parent, CardLayout layout) {
            container = parent;
            cardLayout =  layout;        
        }
    
        @Override
        public void showMenu() {
            cardLayout.show(container, MENU_PANEL);
        }
    
        @Override
        public void showGame() {
            cardLayout.show(container, GAME_MAIN_PANEL);        
        }
    
        @Override
        public void showEndLvl(){
            cardLayout.show(container, LEVEL_PANEL);
        }
    }
    
  • GameMainPanel - 包括2 JPanel' s:

    public class GameMainPanel extends JPanel {
    
        private Container container;
        private GameController controller;
        private BorderLayout layout;
    
        private GamePanel gamePanel;
        private InterfacePanel interfacePanel;
    
        GameMainPanel(GameController contrl,Container parent){
            controller = contrl;
            container = parent;
            setFocusable(true);
            setBackground(Color.WHITE);
            getPreferredSize();
    
            gamePanel = new GamePanel(contrl);
            interfacePanel = new InterfacePanel(contrl);
    
            layout = new BorderLayout();
            setLayout(layout);
            add(gamePanel, BorderLayout.LINE_START);
            add(interfacePanel, BorderLayout.LINE_END);
    
            addComponentListener(new ComponentAdapter() {
                    public void componentShown(ComponentEvent e) {
                            requestFocusInWindow();
                    }
            });
        }
    
        @Override
        public void addNotify() {
            super.addNotify();
            requestFocusInWindow();
        }
    
         public void paint(Graphics g) {
            super.paint(g);
        }
    
        public Dimension getPreferredSize() {
            return new Dimension(800, 600);
        }
    
    }
    
  • GamePanel

    public class GamePanel extends JPanel {
    
        private GameController controller;    
    
        public GamePanel (GameController contrl){        
            controller = contrl;
    
            addKeyListener(new GameAdapter(contrl));
            setFocusable(true);
            setBackground(Color.BLACK);
            getPreferredSize();        
            addComponentListener(new ComponentAdapter() {
    
                    public void componentShown(ComponentEvent e) {
                            requestFocusInWindow();
                    }
                });
        }
    
        @Override
        public void addNotify() {
            super.addNotify();
            requestFocusInWindow();
        }
    
        public Dimension getPreferredSize() {
            return new Dimension(650, 600);
        }
    
        @Override
        public void paint(Graphics g) {
            super.paint(g); 
            Graphics2D g2d = (Graphics2D)g;
    
            Font small = new Font("Helvetica", Font.BOLD, 24);
            FontMetrics metr = this.getFontMetrics(small);
            g.setColor(Color.GREEN);
            g.setFont(small);
            g.drawString("game",300,300);
        }
    
        private class GameAdapter extends KeyAdapter{
    
            private GameController controller;
    
            GameAdapter(GameController contrl){
                controller = contrl;
            }
            public void keyPressed(KeyEvent e) {
                if ((e.getKeyCode() == KeyEvent.VK_ENTER)) {
                    controller.showEndLvl();
                }             
            }
        }
    }
    
  • InterfacePanel

    public class InterfacePanel extends JPanel {
    
        private GameController controller;    
    
        InterfacePanel(GameController contrl){
            setFocusable(true);
            setBackground(Color.WHITE);
            getPreferredSize();
            setSize(150,600);
    
            addComponentListener(new ComponentAdapter() {
                    public void componentShown(ComponentEvent e) {
                            requestFocusInWindow();
                    }
            });
        }
    
        @Override
        public void addNotify() {
            super.addNotify();
            requestFocusInWindow();
        }
    
         public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2d = (Graphics2D)g;
    
            Font small = new Font("Helvetica", Font.BOLD, 24);
            FontMetrics metr = this.getFontMetrics(small);
            g.setColor(Color.GREEN);
            g.setFont(small);
            g.drawString("interface",10,300);
        }
    
        public Dimension getPreferredSize() {
    
            return new Dimension(150, 600);
        }
    }
    
  • LvlEndPanel

    public class LvlEndPanel extends JPanel{
    
        private GameController controller;
    
        public LvlEndPanel(GameController contrl){
            controller = contrl;
    
            setFocusable(true);
            setBackground(Color.BLACK);
            getPreferredSize();           
            addComponentListener(new ComponentAdapter() {
    
                    public void componentShown(ComponentEvent e) {
                            requestFocusInWindow();
                    }
            });
    
            addKeyListener(new KeyListener() {
    
                @Override
                public void keyPressed(KeyEvent e) {
                    if ((e.getKeyCode() == KeyEvent.VK_ENTER)) {
                                controller.showMenu();
                        }                
                }
                @Override
                public void keyTyped(KeyEvent e) {                
                }
                @Override
                public void keyReleased(KeyEvent e) {                
                }
    
            });
        }
    
        @Override
        public void addNotify(){
            super.addNotify();
            requestFocusInWindow();        
        }
    
         public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2d = (Graphics2D)g;
    
            Font small = new Font("Helvetica", Font.BOLD, 24);
            FontMetrics metr = this.getFontMetrics(small);
            g.setColor(Color.GREEN);
            g.setFont(small);
            g.drawString("Level Panel",300,300);
        }
    
         public Dimension getPreferredSize() {        
            return new Dimension(800, 600);
        }
    }
    
  • MenuPanel

    public class MenuPanel extends JPanel{
    
        private GameController controller;
    
        public MenuPanel(GameController contrl){
    
            setFocusable(true);
            setBackground(Color.WHITE);
            getPreferredSize();
            controller = contrl;
    
            addComponentListener(new ComponentAdapter() {
                    public void componentShown(ComponentEvent e) {
                            requestFocusInWindow();
                    }
            });
    
            addKeyListener(new KeyListener() {
    
                @Override
                public void keyTyped(KeyEvent e) {
                }
    
                @Override
                public void keyPressed(KeyEvent e) {
                        if ((e.getKeyCode() == KeyEvent.VK_ENTER)) {
                            controller.showGame();
                        }
                }
    
                @Override
                public void keyReleased(KeyEvent e) {                
                }
    
            });
    
        }
    
        @Override
        public void addNotify() {
            super.addNotify();
            requestFocusInWindow();
        }
    
    
        public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2d = (Graphics2D)g;
    
            Font small = new Font("Helvetica", Font.BOLD, 24);
            FontMetrics metr = this.getFontMetrics(small);
            g.setColor(Color.GREEN);
            g.setFont(small);
            g.drawString("Game Menu", 300,300);
        }
    
        public Dimension getPreferredSize() {        
            return new Dimension(800, 600);
        }
    }
    

updend

当我发布这个时,我只有黑框。我怎样才能解决这个问题?我做错了什么?

提前致谢。

感谢您的编辑。

1 个答案:

答案 0 :(得分:1)

您是控制器将showMenu定义为

public void showMenu() {
    cardLayout.show(container, MENU_PANEL);
}

但是你永远不会添加名称为MENU_PANEL

的任何内容
add(gamePanel, CardLayoutGameController.GAME_PANEL);
add(lvlPanel, CardLayoutGameController.LEVEL_PANEL);
add(gameMainPanel, CardLayoutGameController.GAME_MAIN_PANEL);

将用于gameMainPanel的名称更改为MENU_PANEL或将showMenu更改为使用GAME_MAIN_PANEL而不是

根据示例代码更新

您的布局实际上没有任何问题,(主要)问题是您的MenuPanel paint方法。在可能的情况下,您应该避免在paint方法中加载字体,加载字体的过程可能非常耗时,这会阻止您的面板及时绘制。

相反,可以在构造函数中预加载字体,然后在绘制时应用它,例如......

public class MenuPanel extends JPanel {
    //...
    public MenuPanel(GameController contrl) {
        //...
        Font small = new Font("Helvetica", Font.BOLD, 24);
        setFont(small);
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;

        g.setFont(getFont());
        FontMetrics metr = g.getFontMetrics();
        g.setColor(Color.GREEN);
        g.drawString("Game Menu", 300, 300);
    }
}

这适用于LvlEndPanelInterfacePanelGamePanel ......

旁注

  • addNotify将不再按您配置的方式工作,因为组件只添加一次,而您应该依赖ComponentListener(您是)。更好的解决方案是使用the key bindings API,它可以帮助您克服KeyListener的焦点限制。
  • 通常,您会覆盖paintComponent而不是paintpaint做了很多很容易被破坏的工作,而其他子组件在重新绘制时会引起问题......