0

I've recently been developing software applications which have mostly been very basic, and I have reached a problem.

The application I am developing now has many different menus and screens, which I would like the JFrame to alternate between displaying upon clicks of a button.

I can see surprisingly little information on this given that this is a feature that most applications seem to implement, which makes me wonder if my approach is completely off, however is some example code illustrating this approach.

My question therefore is, a) what is the best way to go about achieving this, and b) what is wrong with my current code? The former question is the most important however.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Demo {
    JFrame frame;
    JButton nextButton = new JButton ("Next Screen");

    public void setup() {
        frame = new JFrame();
        frame.setVisible(true);
        frame.add(new PanelOne());
        frame.pack();
    }


    public class PanelOne extends JPanel { {
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.add(new JLabel("Label One"));
        this.add(new JLabel("Label Two"));
        this.add(new JLabel("Label Three"));
        this.add(new JLabel("Label Four"));
        this.add(new JLabel("Label Five"));
        JButton button = new JButton("Next Screen");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                swapPanel();
            }
        });
        this.add(button);
    } }
    public class PanelTwo extends JPanel {{
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.add(new JButton("Button One"));
        this.add(new JButton("Button Two"));
        this.add(new JButton("Button Three"));
        this.add(new JButton("Button Four"));
        this.add(new JButton("Button Five"));
    }}


    protected void swapPanel() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                frame.removeAll();
                frame.add(new PanelTwo());
                frame.invalidate();
                frame.revalidate();

            }

        });

    }

    public static void main (String[] args) {
        Demo demo = new Demo();
        demo.setup();
    }
}
quantum285
  • 1,032
  • 2
  • 11
  • 23
  • 3
    For swapping displayed components, use [CardLayout](https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html). Also, what is the question? – kiheru Apr 16 '15 at 09:47
  • Thanks for the reply, I've made my question more explicit. I'm asking what the best way to achieve my goal is, and if possible an explanation as to what is wrong with my approach. – quantum285 Apr 16 '15 at 09:52
  • Possible [duplicate](http://stackoverflow.com/q/5654926/230513). – trashgod Apr 16 '15 at 09:55

1 Answers1

3

Use this as your code.....

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Demo {
    JFrame frame;
    JButton nextButton = new JButton ("Next Screen");
    PanelOne p = new PanelOne();
    public void setup() {
        frame = new JFrame();
        frame.setVisible(true);

        frame.add(p);
        frame.pack();
    }


    public class PanelOne extends JPanel { {
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.add(new JLabel("Label One"));
        this.add(new JLabel("Label Two"));
        this.add(new JLabel("Label Three"));
        this.add(new JLabel("Label Four"));
        this.add(new JLabel("Label Five"));
        JButton button = new JButton("Next Screen");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                swapPanel();
            }
        });
        this.add(button);
    } }
    public class PanelTwo extends JPanel {{
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.add(new JButton("Button One"));
        this.add(new JButton("Button Two"));
        this.add(new JButton("Button Three"));
        this.add(new JButton("Button Four"));
        this.add(new JButton("Button Five"));
    }}


    protected void swapPanel() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {


                frame.remove(p);
                frame.add(new PanelTwo());
                frame.invalidate();
                frame.revalidate();

            }

        });

    }

    public static void main (String[] args) {
        Demo demo = new Demo();
        demo.setup();
    }
}

hoping it helped....

CoderNeji
  • 2,056
  • 3
  • 20
  • 31
  • 1
    Bossed it! Made a slight tweak and just used frame.remove(frame.getContentPane().getComponent(0)); as I always have one parent JPanel that I pass to the JFrame. Any idea why the frame.removeAll() wasn't working? – quantum285 Apr 16 '15 at 10:00
  • because removeall() removes the whole componet and for that you have to add a component with a name so that it can be stored to be removed later.... – CoderNeji Apr 16 '15 at 10:02
  • Thanks a lot. I've got one more question if you don't mind. In my example I use SwingUtilities.invokeLater, but it seems to work without it. Is it a good practise to leave it in for the awt event queue's sake? – quantum285 Apr 16 '15 at 10:10
  • See what does SwingUtilities.invokeLater do is.... it executes your Runnable on the AWT event-dispatching thread. It is so because the Swing data structures aren't thread-safe, so to provide programmers with an easily-achievable way of preventing concurrent access to them, the Swing designers laid down the rule that all code that accesses them must run on the same thread.... So use it... its a good practice... – CoderNeji Apr 16 '15 at 10:15
  • If my code helped you then please accept it as an answer – CoderNeji Apr 16 '15 at 10:18