首页 > 解决方案 > 从 jpanel 中删除组件时出现 NullPointerException

问题描述

我正在尝试从 jpanel 中删除一个组件,但它一直给我一个NullpointerException. 我正在尝试从 jpanel 中删除一个组件,然后在其位置添加一个标签。

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;


public class Minefield extends JFrame
{
private final int ROWS= 3;
private final int COLS=3;
public JButton[][] grid ;
private GridBagConstraints c;
private JPanel display;
public Minefield()
{
    grid = new JButton[ROWS][COLS];
    JPanel display = new JPanel();
    add(display);
    display.setLayout(new GridBagLayout());
     c = new GridBagConstraints();  
    c.fill = GridBagConstraints.HORIZONTAL; 
    c.fill = GridBagConstraints.VERTICAL; 
    MouseHandler handler = new MouseHandler();
    for(int row=0;row<ROWS;row++)
    {
        for(int col =0;col<COLS;col++)
        {
            grid[row][col]=new JButton(""+row+","+col);
            c.gridx = col;  
            c.gridy = row;
            display.add(grid[row][col],c);
            grid[row][col].addMouseListener(handler);
        }
    }

}
private class MouseHandler  implements MouseListener
{
    public void mouseClicked(MouseEvent event)
    {
        for(int row=0;row<ROWS;row++)
        {
            for(int col =0;col<COLS;col++)
            {
                if(event.getSource()== grid[row][col])
                {

                    remove(grid[row][col]);
                    display.revalidate();
                }
            }
        }
    }
    public void mousePressed(MouseEvent me){}
    public void mouseReleased(MouseEvent me){}
    public void mouseEntered(MouseEvent me){}
    public void mouseExited(MouseEvent me){}
}

}

这是它给我的错误

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Minefield$MouseHandler.mouseClicked(Minefield.java:48)
    at java.desktop/java.awt.AWTEventMulticaster.mouseClicked(Unknown Source)
    at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
    at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.desktop/java.awt.Component.processEvent(Unknown Source)
    at java.desktop/java.awt.Container.processEvent(Unknown Source)
    at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.EventQueue.access$600(Unknown Source)
    at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

第 48 行是display.revalidate().

标签: javaswing

解决方案


您已经声明了两个名为 的变量display

public class Minefield extends JFrame
{
    // ...

    private JPanel display;
    public Minefield()
    {
        grid = new JButton[ROWS][COLS];
        JPanel display = new JPanel();
        // ...

第二个变量在构造函数中是局部的。当您调用 时display.revalidate(),您正在访问private尚未初始化的字段。

要解决此问题,您只需删除声明:

display = new JPanel();

更好的是,您可以内联初始化字段:

public class Minefield extends JFrame
{
    // ...
    private JPanel display = new JPanel();

然后JPanel display = new JPanel();从构造函数中删除该行。

笔记

您在mouseClicked(). 您不需要任何 for 循环。您可以直接使用event.getSource()相同的效果:

private class MouseHandler  implements MouseListener
{
    public void mouseClicked(MouseEvent event)
    {
        remove(event.getSource());
        display.revalidate();
    }
    public void mousePressed(MouseEvent me){}
    public void mouseReleased(MouseEvent me){}
    public void mouseEntered(MouseEvent me){}
    public void mouseExited(MouseEvent me){}
}

经过仔细检查,我发现这和您的原始代码都有一个缺陷,可能会影响您的应用程序的其他部分,这些部分未在此处显示(或者您尚未编写)。该mouseClicked()函数将从显示中删除一个按钮,但您仍然可以引用grid. 如果您尝试访问grid数组中的按钮并假设它们在JPanel.


推荐阅读