2

I have a JFrame which uses BorderLayout as a layout manager. I also have 2 panels on this JFrame, at CENTER and SOUTH position. The panel on CENTER position is changed dynamically on some user actions (actually when user press "Next" on the bottom panel).

The code is follwing:

private void switchToPanelByState(State state)
{
    this.getContentPane().removeAll();

    JPanel panel = _panels.get(state);
    this.getContentPane().add(panel, BorderLayout.CENTER);

    this.getContentPane().add(_controlPanel, BorderLayout.SOUTH);
    this.pack();
}

The problem is that after a few changes of panels the parts of "old" (from previous panels) GUI elements are appears on the current panel.

And also from time to time i see the following exception:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at javax.swing.JComponent._paintImmediately(Unknown Source)
        at javax.swing.JComponent.paintImmediately(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
        at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at javax.swing.JComponent._paintImmediately(Unknown Source)
        at javax.swing.JComponent.paintImmediately(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
        at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

However I don't know if it's related to the problem.

What is the possible source of these problems? Any advise would be appreciated.

ovk
  • 2,318
  • 1
  • 23
  • 30
  • 3
    Whenever I see the removeAll() method, the first thought that comes to mind is that you should be using a [Card Layout](http://download.oracle.com/javase/tutorial/uiswing/layout/card.html). – camickr Nov 20 '11 at 23:18

1 Answers1

4

BorderLayout accepts only one JComponent in the central Area, then there is no reason to remove()/ removeAll(); your code should be as shown below:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class MyFrame extends JFrame {

    private static final long serialVersionUID = 1L;

    public MyFrame() {
        final JPanel parentPanel = new JPanel();
        parentPanel.setLayout(new BorderLayout(10, 10));
        JButton myButton = new JButton("Add Component ");
        myButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                JPanel childPanel1 = new JPanel();
                childPanel1.setBackground(Color.red);
                childPanel1.setPreferredSize(new Dimension(300, 40));
                JPanel childPanel2 = new JPanel();
                childPanel2.setBackground(Color.blue);
                childPanel2.setPreferredSize(new Dimension(800, 600));

                parentPanel.add(childPanel1, BorderLayout.NORTH);
                parentPanel.add(childPanel2, BorderLayout.CENTER);

                parentPanel.revalidate();
                parentPanel.repaint();

                pack();
            }
        });
        setTitle("My Empty Frame");
        setLocation(10, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        parentPanel.add(myButton, BorderLayout.SOUTH);
        add(parentPanel);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyFrame myFrame = new MyFrame();
            }
        });
    }
}

or directly

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class MyFrame extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel childPanel1 = new JPanel();
    private JPanel childPanel2 = new JPanel();
    private JPanel childPanel3 = new JPanel();

    public MyFrame() {
        childPanel1.setBackground(Color.red);
        childPanel1.setPreferredSize(new Dimension(300, 40));
        childPanel2.setBackground(Color.blue);
        childPanel2.setPreferredSize(new Dimension(300, 40));
        childPanel3.setBackground(Color.yellow);
        childPanel3.setPreferredSize(new Dimension(300, 40));

        JButton myButton = new JButton("Add Component ");
        myButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                add(childPanel2, BorderLayout.CENTER);
                pack();
            }
        });

        setTitle("My Empty Frame");
        setLocation(10, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(childPanel3, BorderLayout.CENTER);
        add(myButton, BorderLayout.SOUTH);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyFrame myFrame = new MyFrame();
            }
        });
    }
} 

2) nobody know what's parameter state is, then without SSCCE isn't possible answering this question

3) I can simulating RepaintManager's Exceptions, when CustomPainting is faster than latency from Native OS

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • mKorbel, thanks for the answer. Unfortunately neither JFrame (this) nor Container (content pane) doesn't have method revalidate. As for "State" - it's just a key to find a correct panel in the HashMap. – ovk Nov 20 '11 at 19:10
  • 2
    this answer is wrong - correct is that the BorderLayout only _shows_ the last added component (in each of its contraint areas), but: all formerly added components with the same constraint are still children of the container. BTW: please dont litter the answer with variants that are only marginally different - choose one (the barest minimum, here that would be the second with only two childPanel fields) and stick to it. – kleopatra Nov 21 '11 at 10:18