1

I want to change the panel dynamically and as this answer show, they recommend to use the cardLayout. But I want to change the whole UI(no old button left) and cardLayout seems not so convenient. So I have the following code:

 JFrame frame = new JFrame ("Key test");
    MyDrawPanel1 dp1 = new MyDrawPanel1(frame);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible (true);
    JPanel p = new JPanel ();
    p.setLayout(new BorderLayout());
    p.add(dp1,BorderLayout.CENTER);

    frame.getContentPane().add(p);
    frame.pack();
    frame.setVisible (true);

And in the MyDrawPanel1 there is a button to change panel:

  public MyDrawPanel1(final JFrame frame) {
    clickButton.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            frame.getContentPane().removeAll();
            //frame.validate();
            frame.getContentPane().add(new MyDrawPanel2());
            ((JPanel)frame.getContentPane()).revalidate();

        }

    });
    this.add(clickButton);

}

Edit:some more codes in MyDrawPanel1.

  JButton clickButton  = new JButton("click");

Image image = new ImageIcon("D:/0.jpg").getImage();
public void paintComponent (Graphics g) {
    super.paintComponent(g);
    g.drawImage(image, 3, 40, null);
}
public Dimension getPreferredSize() {
    if (image != null) {
         return new Dimension(image.getWidth(null), image.getHeight(null));
      }
      return super.getPreferredSize(); // default
}

But the first panel doesn't disappear and I have to minimize it to refresh it so I can see the second panel. My question is the why validate don't work and if there is any other alternatives. Thanks.

Edit:here are the pictures I snipped about the panel.(first panel):enter image description here

(after clicked):enter image description here

Edit: The madProgrammer and Adarsh Singhal provide two ways to solve the problem. The first is the second the panel don't call the super.paintComponent(), so add it then it works fine (as this answer say, it is the eraser so the first panel was gone). The second is calling the frame.repaint(), but I don't understand why?

Community
  • 1
  • 1
Tony
  • 5,972
  • 2
  • 39
  • 58
  • 1
    try `revalidate()`, and whats wrong with CardLayout? – Vince May 15 '14 at 03:21
  • 1
    It's possible that the API didn't consider the panel to be in an invalidate state. – MadProgrammer May 15 '14 at 03:35
  • I think what you need is invalidate(), not validate(). – Alex Suo May 15 '14 at 03:40
  • @MadProgrammer Sorry, but I don't understand what you say. Which panel is in an state of invalidate state. – Tony May 15 '14 at 06:26
  • 1
    Actually, from your screenshot, it looks like you've broken the paint chain by not calling `super.paintXxx`. An actual [runnable example that demonstrates your problem](https://stackoverflow.com/help/mcve) would involve less guess work and better responses – MadProgrammer May 15 '14 at 06:28
  • @VinceEmigh To use cardLayout It seems that I have to retain a button on the frame(like [this](http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html)) to change panel but I want to have new buttons on the new panel. Am I right? – Tony May 15 '14 at 06:37
  • @Tony I'm not sure what you mean. You're saying you don't want the button? Because buttons have nothing to do with `CardLayout`. You change panels by calling `show(Container, String)`. Calling it using an `ActionListener` for buttons is optional. You don't need a button to switch. Im sure MadProgrammer is referring to the panel being flagged invalidated. `revalidate()` invalidates, then validates. He also mentioned calling `super.paint` when you override it, which is important Cut the code down to pure necessities, and post a runnable example. You aren't giving us enough code to work with – Vince May 15 '14 at 07:06
  • Is the second edit enough? – Tony May 15 '14 at 07:46
  • One of your components somewhere isn't calling super.paintXxx, but there not enough code available to determine who is the culprit – MadProgrammer May 16 '14 at 22:10
  • @MadProgrammer Thanks a lot. It indeed the MyDrawPanel2 doesn't calling super.paintComponent() and it works fine now. – Tony May 17 '14 at 12:40

1 Answers1

1

We've to use repaint() to tell the components to repaint themselves. Visualize it as your case. While revalidate is used to update the layouts. So, whenever you add/remove components dynamically, you need to call both of them.

The following written code displays a JFrame set to CardLayout to draw Red dp1(JPanel) completely on JFrame. On dp1, there is a Jbutton. If you click that button, dp1 will be removed & dp2(JPanel) will be drawn. dp2 is Green to distinguish changes. It seems you've forgotten repaint().

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class MyFrame extends JFrame{
    JButton button;
    private static MyFrame frame;
    public MyFrame(){
        this.setSize(400, 400);
        this.setLayout(new CardLayout());
        this.setLocationRelativeTo(null);
        JPanel dp1 = new JPanel();
        dp1.setBackground(Color.RED);
        add(dp1);
        button  = new JButton("Click me to remove dp1 & draw dp2");
        dp1.add (button);
        JPanel dp2 = new JPanel ();
        dp2.setBackground(Color.GREEN);


        button.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                frame.getContentPane().remove(dp1);
                frame.add(dp2);
                frame.revalidate();
                frame.repaint();

            }});

       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible (true);
    }

    public static void main(String[] args) {
        frame = new MyFrame();
    }
}
Adarsh Singhal
  • 362
  • 1
  • 3
  • 12