Question

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?

Était-ce utile?

La solution

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();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top