0

I am trying to use a button to essentially replace a JPanel with another JPanel. However, when I run the code below and click on the button in the window, it displays a blank screen instead of "Instructions". I have called revalidate() and repaint() after the removeAll() method, as other people have stated in other forums, and anything I do to the window (i.e. resizing, minimizing, etc.) doesn't work.

I'm sure it's something stupid that I'm missing, but I've run out of ideas.

Thanks.

public class TitlePage extends JPanel{

private static final long serialVersionUID = 0;
private JButton a;
//The code works without me needing to define an extra JPanel instance variable.

public TitlePage(){

    setLayout(null); 
    setBackground(Color.WHITE);

    JLabel title = new JLabel("2009 AP(R) Computer Science A Diagnostic Exam");
    title.setBounds(175,100,650,50);
    title.setFont(new Font("Times New Roman", Font.PLAIN, 30));
    setVisible(true);
    add(title);


    a = new JButton("Start Diagnostic");
    a.setBounds(400, 300, 200, 50);
    a.setForeground(Color.BLUE);
    a.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            removeAll();
            revalidate();
            repaint();
            add(new Instructions());
            revalidate();
            repaint();

        }
    });
    setVisible(true);
    add(a);

    JLabel disclaimer = new JLabel("*AP(R) is a registered trademark of the College Board, which was not involved in the production of, and does not endorse, this product.");
    disclaimer.setBounds(150,650,750,50);
    disclaimer.setFont(new Font("Times New Roman", Font.PLAIN, 12));
    setVisible(true);
    add(disclaimer);

}

}

The Instructions class contains a simple JLabel.

public class Instructions extends JPanel {

private static final long serialVersionUID = 0;

public Instructions(){

    JLabel instr = new JLabel("Instructions");
    instr.setBounds(0,0,100,50);
    instr.setForeground(Color.BLACK);
    instr.setFont(new Font("Times New Roman", Font.PLAIN, 30));
    setVisible(true);
    add(instr);

}
}
Visruth
  • 3,430
  • 35
  • 48
  • 1
    1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson May 16 '16 at 05:20
  • You're not replacing the `TitlePage` panel with the `Instructions` panel. You're actually removing all the components from `TitlePage` and adding the `Instructions` panel to `TitlePage`. I think the problem is the bounds you've set to this panels, I think `Instructions` is displayed outside of the visible portion of your frame. You should avoid using `null` layouts and positioning components by setting their bounds. – Titus May 16 '16 at 05:32
  • I think you need to use CardLayout instead of removing and adding the panel. CardLayout will do the stuff for you. BTW why do you call `setVisible(true);` after each `add()` you can call after adding all the ui componenets to the container. – Beniton Fernando May 16 '16 at 05:36
  • @Titus Is there a way I can reposition the Instructions panel to where it is at the center of the JFrame or maybe move it to the main class? I tried putting a `setLayout( new FlowLayout())` in the Instructions class that didn't do anything. – Bramble Star May 16 '16 at 05:44
  • *"I can reposition the Instructions panel to where it is at the center of the JFrame or maybe move it to the main class?"* A number of ways, using layouts.. *I tried.." Try posting an MCVE, as I suggested earlier. – Andrew Thompson May 16 '16 at 06:05
  • @AndrewThompson This is the first time I've used JFrame/JPanel, so I wouldn't know what would be an MCVE. I've only used Canvas and Graphics before. – Bramble Star May 16 '16 at 06:24
  • *"his is the first time I've used JFrame/JPanel, so I wouldn't know what would be an MCVE."* An MCVE might be JavaScript or C++. There is no inherent link between MCVE/SSCCE & Swing (or any of its components). If OTOH you mean you are new to programming, then best avoid GUIs until you have experience coding command line apps. – Andrew Thompson May 16 '16 at 06:27

1 Answers1

1

It depends on what you are trying to do. As I see it, you have two options. You can either change the panel within the JFrame. You can very simply do it as follows:

jframe.remove(old_panel)
jframe.add(newPanel);
jframe.revalidate();
jframe.repaint();

Options number two would be changing the contents within the panel and adding the second Panel as a sub panel. doing the following:

JPanel thisPanel = this;
a.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
     for(Component c: thisPanel.getComponents()) {
       thisPanel.remove(c);
     }
     JPanel instruction = new Instruction();
     instruction.setBounds(your_values_here...);
     thisPanel.add(instruction);
     thisPanel.revalidate();
     thisPanel.repaint();
}

Important things to notice here are that thisPanel should be a variable set by the class and do not use 'this' within the action listener, as the 'this' in the action listener refers to the action listener object and not the JPanel.

The reason you need to use the for loop is because you do not want to remove the sub-panel you just added.

If you do not set bounds you will not see your instruction panel as it will be size of 0.

Hope this helps

Jon
  • 36
  • 1
  • 3
  • That makes sense. I can see why the implied `this` is inappropriate in the ActionListener. I will try your suggestion. – Bramble Star May 16 '16 at 07:13