在JFrame上动态更改JPanel的问题

时间:2011-11-20 18:53:18

标签: java swing jframe

我有一个使用BorderLayout作为布局管理器的JFrame。 我在这个JFrame上还有2个面板,位于CENTER和SOUTH位置。 CENTER位置上的面板在某些用户操作上动态更改(实际上当用户按下底部面板上的“下一步”时)。

代码如下:

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();
}

问题是,在对面板进行一些更改后,当前面板上会出现“旧”(来自前面板)GUI元素的部分。

还有时我会看到以下异常:

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)

但我不知道这是否与问题有关。

这些问题的可能来源是什么? 任何建议将不胜感激。

1 个答案:

答案 0 :(得分:4)

BorderLayout只接受中央Area中的一个JComponent,然后没有理由remove()/ removeAll();您的代码应如下所示:

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();
            }
        });
    }
}

或直接

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)没有人知道参数state是什么,然后没有SSCCE就无法回答这个问题

3)当CustomPainting比Native OS的延迟更快时,我可以模拟RepaintManager的异常