简体   繁体   中英

how to change a panel of CardLayout through another panel

In my program I have a wizard based layout. Implemented by CardLayout. So there is a set of classes that extend JPanels. I want to have buttons in each panel to navigate to other panels. fro example, when the program is showing panel one, I want to have a button to show panel 2.

I tired to create a method in main cardlayout panel holder so any other class can change the showing panel by this method, but it does not works and a stackoverflow error come up.

Here are my classes

Base Frame:

public class Base {
        JFrame frame = new JFrame("Panel");
        BorderLayout bl = new BorderLayout();

    public Base(){
        frame.setLayout(bl);
        frame.setSize(800, 600);
        frame.add(new LeftBar(), BorderLayout.WEST);
        frame.add(new MainPanel(), BorderLayout.CENTER);

        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        new Base();
    }
}

Main class that holds sub panels:

public class MainPanel extends JPanel {
    private CardLayout cl = new CardLayout();
    private JPanel panelHolder = new JPanel(cl);

    public MainPanel() {
        NewSession session = new NewSession();
        ChooseSource chooseSource = new ChooseSource();

        panelHolder.add(session, "Session");
        panelHolder.add(chooseSource, "ChooseSource");

        cl.show(panelHolder, "Session");
        add(panelHolder);
    }

    public void showPanel(String panelIdentifier){
        cl.show(panelHolder, panelIdentifier);
    }
}

Sub panel 1

public class NewSession extends JPanel {
    MainPanel ob2 = new MainPanel();

    public NewSession(){
        JButton newSessionBTN = new JButton("Create A New Session");

        newSessionBTN.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                System.out.println("HI");

                ob2.showPanel("ChooseSource");
            }
        });

        add(newSessionBTN);
    }
}

Sub panel 2

public class ChooseSource extends JPanel {

    public ChooseSource(){
        JLabel showMe = new JLabel("Show Me");
        JButton back = new JButton("Back");
        //MainPanel ob = new MainPanel();

        back.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                //ob.showPanel("start");
            }
        });

        add(back);
        add(showMe);
    }
}

As you can see I have button in each sub panel and those buttons must show the other panel after clicking. In later they will also transfer the data from one to another.

ERROR:

Exception in thread "main" java.lang.StackOverflowError
    at java.awt.Component.setFont(Component.java:1899)
    at java.awt.Container.setFont(Container.java:1748)
    at javax.swing.JComponent.setFont(JComponent.java:2751)
    at javax.swing.LookAndFeel.installColorsAndFont(LookAndFeel.java:208)
    at javax.swing.plaf.basic.BasicPanelUI.installDefaults(BasicPanelUI.java:66)
    at javax.swing.plaf.basic.BasicPanelUI.installUI(BasicPanelUI.java:56)
    at javax.swing.JComponent.setUI(JComponent.java:663)
    at javax.swing.JPanel.setUI(JPanel.java:153)
    at javax.swing.JPanel.updateUI(JPanel.java:126)
    at javax.swing.JPanel.<init>(JPanel.java:86)
    at javax.swing.JPanel.<init>(JPanel.java:109)
    at javax.swing.JPanel.<init>(JPanel.java:117)
    at InnerPanels.NewSession.<init>(NewSession.java:21)
    at StrongBaseLayout.MainPanel.<init>(MainPanel.java:22)

The error is longer than this, by repeating last two lines.

How can I make it working?

Also I had another idea to have a next and previous buttons at the bottom of the page to switch panels. But am not sure which one is optimal. Any idea?

Whenever you see an unexpected StackOverflowError always look for the presence of inadvertent recursion, and in fact, that's exactly what you have going on here since MainPanel creates a NewSession object which then creates a new MainPanel object which then creates a new NewSession object which then creates a new MainPanel object .... repeating ad infinitum or until stack memory (hence the stack overflow) runs out.

here:

public class NewSession extends JPanel {
    MainPanel ob2 = new MainPanel();  // *****

and here:

public class MainPanel extends JPanel {
    private CardLayout cl = new CardLayout();
    private JPanel panelHolder = new JPanel(cl);

    public MainPanel() {
        NewSession session = new NewSession();  // *****

Don't do that. Instead take care to create one and only one of each object. Use setter methods or constructor parameters to help you do this.

For example, change to this:

public class NewSession extends JPanel {
    MainPanel ob2;

    NewSession(MainPanel mainPanel) {
       this.ob2 = mainPanel;

and this:

public class MainPanel extends JPanel {
    private CardLayout cl = new CardLayout();
    private JPanel panelHolder = new JPanel(cl);

    public MainPanel() {
        NewSession session = new NewSession(this);

Regarding:

Also I had another idea to have a next and previous buttons at the bottom of the page to switch panels. But am not sure which one is optimal. Any idea?

I'm not sure what you mean here. Define "optimal".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM