java - 如何将 BorderLayout 放入 CardLayout 中?

标签 java swing layout-manager cardlayout border-layout

问题可能不正确,但我不知道如何正确提问。对此我感到很抱歉。

问题在这里:

我的 JFrame 将 CardLayout 作为布局管理器。 我有三个 JPanel,我在它们之间切换。一切都很好,直到我不得不将 2 个 JPanel 添加到其中一个中。现在,我的一个 JPanel 应该包含另外两个 JPanel。我在某处读到这是可能的。所以这个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 和我的旧游戏面板)

现在的样子:

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);
                }
            });
        }
    }
    
  • 游戏 Controller :

    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:

    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);
        }
    
    }
    
  • 游戏面板:

    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();
                }             
            }
        }
    }
    
  • 界面面板

    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);
        }
    }
    
  • 菜单面板:

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

向上倾斜

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

提前致谢。

感谢您的编辑。

最佳答案

您的 Controller 定义 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);
    }
}

这适用于LvlEndPanel , InterfacePanel ,和GamePanel还有...

旁注

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

关于java - 如何将 BorderLayout 放入 CardLayout 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23864045/

相关文章:

java - 实现接口(interface)的类有更多的方法

java - 合并未排序数组的集合以查找共同元素

Java JLabel 不会更新

java - 如何将组件堆叠在另一个组件上以便它们保持垂直尺寸?

java - 错误 java.lang.ClassNotFoundException : reactor. core.scheduler.TimedScheduler

java - 无法实例化目标 [subclassDTO] 的实例。确保 [subclassDTO] 具有非私有(private)无参构造函数

java - 按下的按钮的名称是什么?

java - 通过 Swing 数据库进行实时搜索(或自动完成)

java - JScrollPane 不可见

java - 如何在 Java 中制作这个 3 列分隔符?