问题可能不正确,但我不知道如何正确提问。对此我感到很抱歉。
问题在这里:
我的 JFrame 将 CardLayout
作为布局管理器
。
我有三个 JPanel
,我在它们之间切换。一切都很好,直到我不得不将 2 个 JPanel 添加到其中一个中。现在,我的一个 JPanel
应该包含另外两个 JPanel
。我在某处读到这是可能的。所以这个JPanel
应该有BorderLayout
。应该是这样的:
这是我之前的:
我的
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); } }
然后我添加了两个 JPanel
类 InterfacePanel
和 GameMainPanel
(其中应该包括这个 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
而不是paint
。paint
做了很多很容易被破坏的工作,并且其他子组件在重新绘制时可能会导致问题......
关于java - 如何将 BorderLayout 放入 CardLayout 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23864045/