【问题标题】:Switching between JPanels在 JPanel 之间切换
【发布时间】:2012-09-17 23:54:34
【问题描述】:

我正在尝试制作游戏。游戏中有几个不同的屏幕,例如主菜单和实际游戏屏幕。其中每一个都是一个单独的 jpanel 扩展。我已将它们中的每一个添加到我的 JFrame 中,这是一个名为 Game 的类。在我的游戏课中,我有以下方法

public void addPanel( JPanel p ) {
    panels.add( p ); // An array of all the different panels I need
    this.getContentPane().add( p );
}

public void switchToPanel( JPanel p ) {
    for ( JPanel somePanel : panels ) {
        somePanel.setVisible( false );
    }

    p.setVisible( true );
    repaint();
}

重点是我有许多不同的面板,当我需要显示一个特定的面板时,例如菜单屏幕,我调用 switchToPanel(myPanel)。基本上只是隐藏每个面板,然后取消隐藏我需要查看的面板。唯一的问题是这些面板在我切换到它们时没有出现。唯一会出现的是我最后添加的面板。在Objective C中,我一直使用这种技术在视图之间切换,我从来没有遇到过任何问题。 java中不允许这种事情吗?

编辑:现在我在切换后调用 repaint(),但它仍然不起作用

【问题讨论】:

  • 有一段时间没有碰过这些,但我认为如果你想看到它,你需要画/重新画框架。

标签: java arraylist jframe jpanel visible


【解决方案1】:

你可以做很多不同的事情来达到同样的效果。

我提出的第一个建议是使用 CardLayout (How to Use CardLayout),因为这是它的设计初衷。

另一个是使用JTabbedPane (How to use Tabbed Panes)

【讨论】:

  • 是的,我认为 cardLayout 是要走的路。
  • @SeanF 它旨在做你想做的事,为什么要重新发明轮子(我现在很懒;))
  • 我实际上想通了,由于某种原因,每次我将 jpanel 添加到我的框架时,我都必须调用 pack() 。我不能只添加它们然后调用 pack(),我必须在添加每个面板后调用它一次。奇怪!
  • @ChristianDaley 小心pack()。如果内容的大小发生变化,框架的大小也会发生变化。这可能不是你想要的效果。最好使用invalidate()repaint() ...或CardLayout,这将是一个更好的解决方案;)
  • 感谢提示,但是我添加的所有 jpanel 都初始化为与我的主 jframe 相同的宽度和高度,并且宽度和高度不会改变。
【解决方案2】:

如果您正在制作游戏,请在与EDT 不同的单独线程中制作它。大多数游戏通过不更改面板来显示不同的屏幕,但它们使用单​​个面板,并根据GameState 在该面板上进行渲染。

这是一个例子。

public class MyGame extends JPanel implements Runnable {

    public static enum GameState {
        MENU, INTRO, LEVELS, END, TITLES
    }

    GameState state = GameState.MENU;

    public MyGame(){
        setDoubleBuffered(true);
        // Initialize the resources
        new Thread(this).start();
    }

    public void update(long elapsedTime){
        switch (state){
            case MENU:
                // Show the menu
                break;
            ....
        }
    }

    private void GameLoop(){
        // Game Loop goes here
    }

    public void run(){
        GameLoop();
    }

    public void paint(Graphics g){
        // switch and draw your game
    }

    public static void main(String[] args){
        JFrame f = new JFrame("MyGame");
        f.setSize(640, 480);
        f.add(new MyGame());
        f.setVisible(true);
    }

}

如果一种状态,即菜单已完成,请更改state 变量。在您自己制作之前,请先学习使用GameEngine

【讨论】:

    【解决方案3】:

    如果您想在两个面板之间切换,请将这些面板添加到另一个 JPanel 并使用 cardLayout。然后,在添加 JPanel 之前删除当前的。像这样:

    parentPanel.removeAll();
    parentPanel.repaint();
    parentPanel.revalidate();
    
    parentPanel.add(childPanel1);
    parentPanel.repaint();
    parentPanel.revalidate();
    

    同样对其他子面板执行相同的操作。

    【讨论】:

      【解决方案4】:
          public static void main(String[] args) {
              JFrame jFrame = new JFrame("Test");
              jFrame.setSize(500, 500);
              jFrame.setLocationRelativeTo(jFrame.getOwner());
              jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              jFrame.setLayout(new BorderLayout());
              var jPanel = new JPanel(new BorderLayout());
      
      
              jFrame.add(jPanel, BorderLayout.CENTER);
      
              AtomicBoolean b = new AtomicBoolean(false);
      
              jFrame.add(new JButton("Switch") {
                  {
                      addActionListener(e -> {
                          b.set(!b.get());
      
                          jPanel.removeAll();
                          jPanel.repaint();
                          jPanel.revalidate();
      
                          jPanel.add(b.get() ? new JPanel() {
                              @Override
                              protected void paintComponent(Graphics g) {
                                  setBackground(Color.RED);
                                  super.paintComponent(g);
                              }
                          } : new JPanel() {
                              @Override
                              protected void paintComponent(Graphics g) {
                                  setBackground(Color.GREEN);
                                  super.paintComponent(g);
                              }
                          });
                          jPanel.repaint();
                          jPanel.revalidate();
      
                      });
                  }
              }, BorderLayout.SOUTH);
      
              jFrame.setVisible(true);
          }
      

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多