cam1488
cam1488

Reputation: 3

How to completely get rid of a JPanel and everything in it?

How to completely get rid of a JPanel and everything in it while running?

package textgame;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class EscapeFromPrison extends JFrame implements ActionListener{
    JButton startGameButton;
    JButton creditsButton;

    JButton choice1;
    Button choice2;

    JLabel mainTitleLabel;
    JLabel question;
    JLabel space;
    JLabel credits;

    JPanel titleScreen;

    public EscapeFromPrison(){
        super("Escape From Prison");
        setLookAndFeel();
        setSize(500,500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        mainTitleLabel = new JLabel("<html>Escape From Prison</html>");

        startGameButton = new JButton("<html>START<html>");
        startGameButton.setActionCommand("StartGameButton");

        creditsButton = new JButton("<html>CREDITS</html>");
        creditsButton.addActionListener(this);
        creditsButton.setActionCommand("CreditsButton");

        question = new JLabel("");
        space = new JLabel("");
        credits = new JLabel("");

        choice1 = new JButton("");
        choice2 = new JButton("");

        JPanel titleScreen = new JPanel();
        BoxLayout titleScreenLayout = new BoxLayout(titleScreen,      BoxLayout.Y_AXIS);
        titleScreen.setLayout(titleScreenLayout);
        titleScreen.add(mainTitleLabel);
        titleScreen.add(startGameButton);
        titleScreen.add(creditsButton);
        add(titleScreen);

        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent buttonClick){
        String event = buttonClick.getActionCommand();

In this if statement I want to get rid of mainTitleLabel, startGameButton, and creditsButton. So question can be in the top left position, cause right now they are currently invisible and the question is in the top right position. I am using grid layout.

            if(event.equals("StartGameButton")){
            GridLayout grid = new GridLayout(2,2);
            setLayout(grid);

            question.setText("<html>text</html>");
            choice1.setActionCommand("");
            choice1.setText("");
            choice2.setActionCommand("");
            choice2.setText("");

            mainTitleLabel.setVisible(false);
            startGameButton.setVisible(false);
            creditsButton.setVisible(false);

            add(question);
            add(choice1);
            add(choice2);

            setVisible(true);

        }
        if(event.equals("CreditsButton")){
            FlowLayout flo = new FlowLayout();
            setLayout(flo);

            credits.setText("<html></html>");

            mainTitleLabel.setVisible(false);
            startGameButton.setVisible(false);
            creditsButton.setVisible(false);

            add(credits);

            setVisible(true);
        }
    }

    private void setLookAndFeel(){
        try{
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        }catch(Exception exc){
            //ignore error
        }
    }

    public static void main(String[] arguments){
        EscapeFromPrison frame = new EscapeFromPrison();
    }
}

Upvotes: 1

Views: 113

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

The basic problem to your current code is startGameButton is never registered to an ActionListener, so it will never do anything.

The large issue is your code is going to become massively complicated to manage as you add more content. A better solution would be to separate each view in it's own class, which you can then manage independently and switch in and out as you need.

This is a beginning of the concept of Model-View-Controller, where you separate your functionality into self contained domains which can communicate via something like a observer pattern (as one idea).

With this you can use a CardLayout to make it easier to switch between views more simply.

Basic example...

This is just one of many possible ways to achieve this

First, we need to define some kind of "controller" which can be used to control what is been made visible. We uses interfaces as the primary contract as they limit the exposure of the implementation and define the exact contract that we expect to be maintained between class, this is commonly known as "program to interfaces", see Smarter Java development and Code to Interface for more details

public interface CardGameController {
    public void showMainMenu();
    public void showQuestion();
    public void showCredits();
}

Now, because I want to use a CardLayout as the underlying mechanism for controlling the views, I need a implementation of the CardGameController which can do this...

public class DefaultCardGameController implements CardGameController {
    
    public static final String MAIN_MENU_PANE = "mainMenuPane";
    public static final String CREDITS_PANE = "creditsPane";
    public static final String QUESTION_PANE = "questionPane";
    
    private Container parent;
    private CardLayout cardLayout;

    public DefaultCardGameController(Container parent, CardLayout cardLayout) {
        this.parent = parent;
        this.cardLayout = cardLayout;
    }

    public Container getParent() {
        return parent;
    }

    public CardLayout getCardLayout() {
        return cardLayout;
    }
    
    protected void show(String name) {
        getCardLayout().show(getParent(), name);
    }

    @Override
    public void showMainMenu() {
        show(MAIN_MENU_PANE);
    }

    @Override
    public void showCredits() {
        show(CREDITS_PANE);
    }

    @Override
    public void showQuestion() {
        show(QUESTION_PANE);
    }
    
}

Have a look at How to Use CardLayout for more details

Now, we need the view we want to manage...

public class MenuPane extends JPanel {

    private JButton startGameButton;
    private JButton creditsButton;
    private JLabel mainTitleLabel;
    
    private CardGameController controller;

    public MenuPane(CardGameController controller) {
        this.controller = controller;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        
        mainTitleLabel = new JLabel("<html>Escape From Prison</html>");

        startGameButton = new JButton("<html>START<html>");
        startGameButton.setActionCommand("StartGameButton");
        startGameButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                controller.showQuestion();
            }
        });

        creditsButton = new JButton("<html>CREDITS</html>");
        creditsButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                controller.showCredits();
            }
        });
        creditsButton.setActionCommand("CreditsButton");
        
        add(mainTitleLabel, gbc);
        add(startGameButton, gbc);
        add(creditsButton, gbc);
    }

}

public class QuestionPane extends JPanel {

    private JButton choice1;
    private JButton choice2;

    private JLabel question;
    
    private CardGameController controller;

    public QuestionPane(CardGameController controller) {
        this.controller = controller;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        
        question = new JLabel("The meaning of life, the universe and everything!?");
        choice1 = new JButton("42");
        choice2 = new JButton("46");
        
        add(question, gbc);
        
        JPanel panel = new JPanel();
        panel.add(choice1);
        panel.add(choice2);
        
        gbc.gridy++;
        add(panel, gbc);
        
        // Have some mechanism to control the questions
    }

}

public class CreditsPane extends JPanel {
    
    private JLabel credits;
    
    private CardGameController controller;

    public CreditsPane(CardGameController controller) {
        this.controller = controller;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        credits = new JLabel("Happy Bunnies");
        add(credits);
    }
    
}

And finally, the "master" view which brings it all together...

public class EscapeFromPrison extends JPanel {

    private MenuPane menuPane;
    private QuestionPane questionPane;
    private CreditsPane creditsPane;

    public EscapeFromPrison() {

        CardLayout cardLayout = new CardLayout();
        setLayout(cardLayout);
        DefaultCardGameController controller = new DefaultCardGameController(this, cardLayout);

        menuPane = new MenuPane(controller);
        questionPane = new QuestionPane(controller);
        creditsPane = new CreditsPane(controller);

        add(menuPane, DefaultCardGameController.MAIN_MENU_PANE);
        add(questionPane, DefaultCardGameController.QUESTION_PANE);
        add(creditsPane, DefaultCardGameController.CREDITS_PANE);

        controller.showMainMenu();
    }

    private static void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                            "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            //ignore error
        }
    }

    public static void main(String[] arguments) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                setLookAndFeel();
                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new EscapeFromPrison());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

Now, this is a very limited example, which takes what you have already done and demonstrates some basic principles.

Because you'll be asking more then one question, you will need some way to manage the questions (and answers) more efficiently, this would be best done by some kind of model which contained all the questions, possible answers and the users answer. This way, you would get away with just a single question view, but which could use the information in the question model to reconfigure itself to display each new question

For example

Upvotes: 3

Related Questions