1

I have a program where I have a JFrame with a JButton in it. When the user clicks the JButton, all Components of the JFrame are removed, and a JPanel with red background is added to it.

When I click the JButton, that red JPanel does not become visible unless I resize the JFrame (I am using Windows 7). Is there a way to achieve what I want without having to manually resize the JFrame?

Here is a part of the code I am using:

public class Demo implements ActionListener{
    public static void main(String args[]){
           ...............
        button.addActionListener(this); //'button' is an object of Jbutton class.
        frame.setVisible(true); //'frame' is an object of JFrame class.
        ............
    }

    public void actionPerformed(ActionEvent ae){
        frame.removeAllComponents();
        frame.add(panel1); //panel1 is an object of Jpanel class with red  background.

        /* Here is where my problem lies.
           panel1 is not visible to me unless I manually resize the JFrame. */
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
awareeye
  • 3,051
  • 3
  • 22
  • 22

3 Answers3

7

For removing (and then, for example, add new JComponents) JComponents from JPanel or from top-level containers you have to call, only once and on the end of the action:

revalidate();
repaint();

And if you only resize or change JComponents:

validate();
repaint();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • is a `repaint()` really necessary? – mre Jul 01 '11 at 12:31
  • @little bunny foo foo for correct work for LayoutManager yes, for example http://stackoverflow.com/questions/6390240/dynamic-generation-of-buttons-in-java/6395105#6395105 – mKorbel Jul 01 '11 at 12:36
  • 1
    could you see my post? I would like for your opinion on my findings. :) – mre Jul 01 '11 at 13:17
  • 2
    Just use revalidate() all the time. There is no need to make a distinction between adding/removing and changing, The way I look at it is that invoking revalidate() is to make sure the layout manager is invoked and changing the size of a component may affect the layout. – camickr Jul 01 '11 at 15:16
  • It's impossible to invoke `revalidate()` on a top-level container. As suggested by @Andrew Thompson, I think using `CardLayout` is more appropriate in this situation. – mre Jul 01 '11 at 15:28
  • I am changing the size of components and validate() is not working. revalidate() is working though. tks – Vincent James Oct 21 '13 at 15:18
5

For me, this was a bit of an oddity. As it turned out, invoking remove(Component comp), adding the new JPanel, and then invoking pack() worked for me.

public class Demo{

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI(){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel();
        final JButton button = new JButton("Press Me");
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                frame.remove(panel);

                final JPanel redPanel = new JPanel(){

                    @Override
                    public Dimension getPreferredSize(){
                        return new Dimension(200, 200);
                    }

                    @Override
                    protected void paintComponent(Graphics g){
                        Graphics g2 = g.create();

                        g2.setColor(Color.RED);
                        g2.fillRect(0, 0, getWidth(), getHeight());

                        g2.dispose();
                    }
                };

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

        panel.add(button);
        frame.add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

BEFORE PRESSING THE BUTTON

enter image description here

AFTER PRESSING THE BUTTON

enter image description here

ODDITIES

  1. Invoking removeAll() actually caused the GUI to freeze. It seems that this event has occurred before. This occurred even after I attempted to remove the action listener prior to removal of all components.
  2. I did not need to invoke any of the validate methods, or even repaint the GUI.
mre
  • 43,520
  • 33
  • 120
  • 170
  • Invoking *pack()* more than once is not good programmatically speaking at all, as seen in my post here: http://stackoverflow.com/questions/34604487/changing-on-screen-component-for-jframe-is-clunky-and-messy-java Calling *pack()* creates a race condition in which components being allocated into memory and being displayed on screen do not happen in a linear order like you may think. If you want to remove something then use **CardLayout** and include two panes, one with and one without the certain component and then flip to the panes when need be. **You should only call pack() once.** – Code Doggo Mar 22 '16 at 02:13
-1

you have to force a repaint() in the frame so the frame have to repaint itself.

Java_Waldi
  • 924
  • 2
  • 12
  • 29