Search code examples
javaswingcardlayout

Button in CardLayout not working


So I'm using cardLayout in one of my programs and I'm trying to make it so that when you click a button the next panel loads. I have a panelHolder class where the cardlayout is held and every time the button on the panel is pressed, it would call a method in the panelHolder class that depending on the button sets a certain boolean variable to true and calls repaint (where the panels are shown). For some reason my button isn't working and I can't seem to find out why. Can someone help me?

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.Arrays;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;

public class SheetReader101 extends JFrame {
    public SheetReader101(){
        super("SheetReader101");
        setSize(2000,1000);
        setLocation(0,0);
        setResizable(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        PanelHolder pg2 = new PanelHolder();
        setContentPane(pg2);
        setVisible(true);
    }
    public static void main(String[]args){
        SheetReader101 z1 = new SheetReader101();
    }
}
class PanelHolder extends JPanel { // HERE
    CardLayout clayout = new CardLayout();
    PianoGameContent x;
    tutorial y;
    boolean [] paneldecide;
    PanelHolder() {
        super();
        y = new tutorial();
        x = new PianoGameContent();
        setLayout(clayout);
        this.add("Tutorial", y);
        this.add("FreePlay Mode", x);
        paneldecide = new boolean[15];
    }
        public static void main(String[]args){
            PanelHolder z1 = new PanelHolder();
            z1.run();
        }
          public void run(){
            layoutShower(0);
         }
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            }
        public void layoutShower (int decide){
            {
                PianoGameContent y2 = new PianoGameContent();
                PanelHolder.this.add("Piano", y2);
                System.out.println("intro slide run");
                if(decide == 1){
                    PanelHolder.this.add("Piano", y2);
                    System.out.println("testing11");
                    clayout.show(PanelHolder.this,"Piano");
            }
            }
        }
    }

Solution

  • I "suspect" that the core problem has to do with the original code you posted, where you're making a new instance of PanelHolder in your child view's ActionListener and then are attempting to switch views, this new instance has no relationship to the instance that is on the screen.

    There are a few ways you can manage CardLayout, my preferred way is to use some kind of "navigation" controller which defines how navigation works, for example, you could have "next" and "previous" or "back", or you could define the actual views that can be displayed, ie showMenuView, showTutorialView etc, depending on how much control you want to give your sub views.

    The following is a simple example which demonstrates the basic idea, it uses a enum to define the available views (as it has more meaning than 0, 1... and I don't need to remember the actual names of the views, the IDE can provide auto correct for that ;))

    I create and add each view up front when I create the PanelHolder, I also pass each view an instance of the NavigationController, so they can interact with it

    import java.awt.CardLayout;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class JavaApplication1013 {
    
        public static void main(String[] args) {
            new JavaApplication1013();
        }
    
        public JavaApplication1013() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new PanelHolder());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public enum View {
            MENU,
            TUTORIAL,
            FREEPLAY;
        }
    
        public interface NavigationController {
            public void showView(View view);
        }
    
        public class PanelHolder extends JPanel implements NavigationController {
    
            private CardLayout cardLayout;
    
            public PanelHolder() {
                cardLayout = new CardLayout();
                setLayout(cardLayout);
    
                add(new MenuView(this), View.MENU.name());
                add(new TutorialView(this), View.TUTORIAL.name());
                add(new FreePlayView(this), View.FREEPLAY.name());
            }
    
            @Override
            public void showView(View view) {
                cardLayout.show(this, view.name());
            }
    
        }
    
        public abstract class ViewPane extends JPanel {
            private NavigationController controller;
    
            public ViewPane(NavigationController controller) {
                this.controller = controller;
            }
    
            public NavigationController getController() {
                return controller;
            }
    
            protected void showView(View view) {
                controller.showView(view);
            }
    
        }
    
        public class MenuView extends ViewPane {
    
            public MenuView(NavigationController controller) {
                super(controller);
    
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                gbc.fill = GridBagConstraints.HORIZONTAL;
    
                JButton tut = new JButton("Tutorial");
                JButton freePlay = new JButton("Free Play");
    
                add(tut, gbc);
                add(freePlay, gbc);
    
                tut.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        showView(View.TUTORIAL);
                    }
                });
                freePlay.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        showView(View.FREEPLAY);
                    }
                });
            }
    
        }
    
        public class TutorialView extends ViewPane {
    
            public TutorialView(NavigationController controller) {
                super(controller);
    
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
    
                JButton menu = new JButton("Menu");
    
                add(new JLabel("Tutorial"), gbc);
                add(menu, gbc);
    
                menu.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        showView(View.MENU);
                    }
                });
            }
    
        }
    
        public class FreePlayView extends ViewPane {
    
            public FreePlayView(NavigationController controller) {
                super(controller);
    
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
    
                JButton menu = new JButton("Menu");
    
                add(new JLabel("Free Play"), gbc);
                add(menu, gbc);
    
                menu.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        showView(View.MENU);
                    }
                });
            }
    
        }
    }
    

    Take a closer look at How to Use CardLayout for more details