ovk
ovk

Reputation: 2358

Problems dynamically changing JPanels on JFrame

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.

Upvotes: 2

Views: 3251

Answers (1)

mKorbel
mKorbel

Reputation: 109815

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

Upvotes: 4

Related Questions