Переключение между JPanels

Я пытаюсь сделать игру. В игре есть несколько разных экранов, таких как главное меню и собственно игровой экран. Каждое из них является отдельным расширением 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() после переключения, но он все еще не работает


person Christian Daley    schedule 17.09.2012    source источник
comment
давно не трогал их, но я думаю, что вам нужно покрасить / перекрасить рамку, если вы хотите это увидеть.   -  person Sean F    schedule 18.09.2012


Ответы (3)


Вы можете сделать несколько разных вещей, чтобы добиться того же эффекта.

Первое, что я могу предложить, это использовать CardLayout (Как использовать CardLayout), поскольку именно для этого он и был разработан.

Другой вариант — использовать JTabbedPane (Как использовать панели с вкладками)

person MadProgrammer    schedule 17.09.2012
comment
да, я думал, что cardLayout - это то, что нужно. - person Sean F; 18.09.2012
comment
@SeanF Он предназначен для того, чтобы делать то, что вы хотите, зачем изобретать велосипед (сейчас я ленив;)) - person MadProgrammer; 18.09.2012
comment
На самом деле я понял это, по какой-то причине мне приходится вызывать pack() каждый раз, когда я добавляю jpanel в свой фрейм. Я не могу просто добавить их все, а затем вызвать pack(), я должен вызывать его один раз после добавления каждой панели. Странный! - person Christian Daley; 18.09.2012
comment
@ChristianDaley Будьте осторожны с pack(). Если размер содержимого изменится, размер фрейма изменится. Это может быть не тот эффект, который вы хотите. Лучше использовать invalidate() и repaint() ... или CardLayout, что было бы лучшим решением;) - person MadProgrammer; 18.09.2012
comment
Спасибо за подсказку, но все jpanels, которые я добавляю, инициализируются с той же шириной и высотой, что и мой основной jframe, а ширина и высота не меняются. - person Christian Daley; 18.09.2012

Если вы делаете игру, вы делаете это в отдельной теме, отличной от 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, прежде чем делать это самостоятельно.

person Sri Harsha Chilakapati    schedule 18.09.2012

Если вы хотите переключаться между двумя панелями, добавьте эти панели в другую JPanel и используйте cardLayout. Затем перед добавлением JPanel удалите текущий. Как это:

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

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

Аналогичным образом сделайте то же самое для других дочерних панелей.

person NamelyProgrammer    schedule 18.05.2017