How to change CardLayout panels from a separate pa

2019-08-15 23:58发布

问题:

My software layout is kinda wizard-base. So the base panel is divided into two JPanels. One left panel which never changes. And one right panel that works with CardLayout. It has many sub-panels and show each one of them by a method.

I can easily go from one inner panel to another one. But I want to have a button in left panel and change panels of the right side.

Here is a sample code which you can run it:

BASE:

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) throws IOException {
        // TODO code application logic here
        new Base();
    }
}

Left side

public class LeftBar extends JPanel{
    JButton button;
    MainPanel mainPanel = new MainPanel();

    public LeftBar(){
        setPreferredSize(new Dimension(200, 40));
        setLayout(new BorderLayout());
        setBackground(Color.black);

        button = new JButton("Show Second Page");
        button.addActionListener(new ActionListener(){
           @Override
           public void actionPerformed(ActionEvent ae) {
               mainPanel.showPanel("secondPage");
           }

       });

       add(button, BorderLayout.NORTH);
    }
}

Right Side

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

    public MainPanel(){
        FirstPage firstPage = new FirstPage(this);
        SecondPage secondPage = new SecondPage(this);

        setLayout(new GridLayout(0,1));

        panelHolder.add(firstPage, "firstPage");
        panelHolder.add(secondPage, "secondPage");

        cl.show(panelHolder, "firstPage");
        add(panelHolder);

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

Inner panels for right side:

public class FirstPage extends JPanel {
    MainPanel mainPanel;
    JButton button;

    public FirstPage(MainPanel mainPanel) {
       this.mainPanel = mainPanel;
       setBackground(Color.GRAY);

       button = new JButton("Show page");
       button.addActionListener(new ActionListener(){
           @Override
           public void actionPerformed(ActionEvent ae) {
               mainPanel.showPanel("secondPage");
           }

       });

       add(button);
    }
}



public class SecondPage extends JPanel{
    MainPanel mainPanel;
    JButton button;
    public SecondPage(MainPanel mainPanel){
       this.mainPanel = mainPanel;
        setBackground(Color.white);
       add(new JLabel("This is second page"));
    }
}

And this is a picture to give you the idea:

As I explained, I can travel "from first" page to "second page" by using this method: mainPanel.showPanel("secondPage"); or mainPanel.showPanel("firstPage");.

But I also have a JButton in the left bar, which I call the same method to show the second panel of the CardLayout. But it does not work. It doesnt give any error though.

Any idea how to change these CardLayout panels from outside of panels?

回答1:

The problem is that LeftBar has mainPanel member that is initialized to a new instance of MainPanel. So you have two instances of MainPanel, one allocated in Base and added to the frame, the other one allocated in LeftBar.

So LeftBar executes mainPanel.showPanel("secondPage"); on a second instance of MainPanel which is not even a part of a visual hierarchy. To fix this just pass an existing instance of MainPanel to the constructor of LeftBar. You already do this in FirstPage and SecondPage.