3

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 :)

GarethR
  • 43
  • 4
  • you can use jPanel.setVisible(true); or jPanel.setVisible(false); to control the visibility of component, please make changes according to your need and use jPanel.setVisible(true); or jPanel.setVisible(false); method. I would prefer defining button in JPanel you can use toggle button in your MainFrame class and initiate your jpanel in MainFrame then control the visibility – Noman ali abbasi Apr 09 '20 at 12:03
  • 1
    I would say that your question has been asked and answered several times, for example [How do I change JPanel inside a JFrame on the fly?](https://stackoverflow.com/questions/218155/how-do-i-change-jpanel-inside-a-jframe-on-the-fly) and [How can I replace one JPanel with another JPanel in the same position?](https://stackoverflow.com/questions/26170974/how-can-i-replace-one-jpanel-with-another-jpanel-in-the-same-position). – Abra Apr 09 '20 at 12:50

2 Answers2

4

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));
    }
}
George Z.
  • 6,643
  • 4
  • 27
  • 47
3

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"));
    }
}
c0der
  • 18,467
  • 6
  • 33
  • 65
  • This is the exact solution I was looking for! Thank you very much :) – GarethR Apr 09 '20 at 12:56
  • 1
    I am glad it helps. Note that I narrowed the solution as much as possible to make it simple. The solution offered by [George Z.](https://stackoverflow.com/a/61121300/3992939) is a bit wider and more general – c0der Apr 09 '20 at 12:59