GarethR
GarethR

Reputation: 43

How to swap JPanel's from an action in a JPanel

I am new(ish) to Java Swing but I have not been able to find an elegant solution to my issue so I thought I'd raise a question here.

I am trying to make my current JPanel change to another JPanel based on a button click event from within the current JPanel. In essence just hiding one panel and displaying the other. I feel this can be done within my MainFrame class however I'm not sure how to communicate this back to it. Nothing I am trying simply seems to do as desired, I'd appreciate any support. Thanks

App.java

public static void main(final String[] args) {
    MainFrame mf = new MainFrame();
}

MainFrame.java

public class MainFrame extends JFrame {

    public MainFrame(){
        setTitle("Swing Application");
        setSize(1200, 800);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setVisible(true);

        // First Page Frame switch
        getContentPane().add(new FirstPage());

    }
}

FirstPage.java

public class FirstPage extends JPanel {

    public FirstPage() {
        setVisible(true);
        JButton clickBtn = new JButton("Click");
        clickBtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                // Change to SecondPage JPanel here.
            }
        });
        add(clickBtn);
    }
}

SecondPage.java

public class SecondPage extends JPanel {

    public SecondPage() {
        setVisible(true);
        add(new JLabel("Welcome to the Second Page"));

    }
}

Any more information needed, please ask thanks :)

Upvotes: 3

Views: 227

Answers (2)

c0der
c0der

Reputation: 18792

CardLayout is the right tool for the job. You can simply create the ActionListener used to swap pages in JFrame class, and pass a reference of it to FirstPage:

import java.awt.CardLayout;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class MainFrame extends JFrame {

    public MainFrame(){
        setTitle("Swing Application");
        setSize(1200, 800);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLocationByPlatform(true);

        //Create card layout and set it to the content pane 
        CardLayout cLayout = new  CardLayout();
        setLayout(cLayout);

        //create and add second page to the content pane 
        JPanel secondPage = new SecondPage();
        add("SECOND",secondPage);

        //create an action listener to swap pages 
        ActionListener listener = actionEvent ->{
            cLayout.show(getContentPane(), "SECOND");
        };

        //use the action listener in FirstPage
        JPanel firstPage = new FirstPage(listener);
        add("FIRST", firstPage);
        cLayout.show(getContentPane(), "FIRST");
        setVisible(true);
    }

    public static void main(String[] args) {
        new MainFrame();
    }
}

class FirstPage extends JPanel {

    public FirstPage(ActionListener listener) {
        JButton clickBtn = new JButton("Click");
        clickBtn.addActionListener(listener);
        add(clickBtn);
    }
}

class SecondPage extends JPanel {
    public SecondPage() {
        add(new JLabel("Welcome to the Second Page"));
    }
}

Upvotes: 3

George Z.
George Z.

Reputation: 6808

I think the best way is to use CardLayout. It is created for such cases. Check my example:

public class MainFrame extends JFrame {
    private CardLayout cardLayout;

    public MainFrame() {
        super("frame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        cardLayout = new CardLayout();
        getContentPane().setLayout(cardLayout);

        getContentPane().add(new FirstPage(this::showPage), Pages.FIRST_PAGE);
        getContentPane().add(new SecondPage(this::showPage), Pages.SECOND_PAGE);

        setLocationByPlatform(true);
        pack();
    }

    public void showPage(String pageName) {
        cardLayout.show(getContentPane(), pageName);
    }

    public static interface PageContainer {
        void showPage(String pageName);
    }

    public static interface Pages {
        String FIRST_PAGE = "first_page";
        String SECOND_PAGE = "second_page";
    }

    public static class FirstPage extends JPanel {
        public FirstPage(PageContainer pageContainer) {
            super(new FlowLayout());

            JButton button = new JButton("next Page");
            button.addActionListener(e -> pageContainer.showPage(Pages.SECOND_PAGE));
            add(button);
        }
    }

    public static class SecondPage extends JPanel {
        public SecondPage(PageContainer pageContainer) {
            super(new FlowLayout());

            add(new JLabel("This is second page."));

            JButton button = new JButton("Go to first page");
            button.addActionListener(e -> pageContainer.showPage(Pages.FIRST_PAGE));
            add(button);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true));
    }
}

Upvotes: 4

Related Questions