java - 从 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()
.
解决方案
您已经声明了两个名为 的变量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
.
推荐阅读
- listview - 将按钮与没有 ListView 间隔的 Xamarin.Forms 网格底部对齐
- list - 将 selected="selected" 更改为选项列表中的第一个值
- azure - Azure DevOps 发布包含已修改文件列表的电子邮件通知(提交日志)
- vmware - 尽管 VMWare 环境中端口组的 VLAN ID 错误,但带有 VLAN 标记的镜像流量仍然通过
- python-3.x - 当 conda 说安装了 1.20.1 时,为什么 Python 会在我的 dask 环境中加载 numpy 1.20.0?
- spring-boot - NameNotFound 异常:Spring Boot (2.2.7.RELEASE)、嵌入式 Tomcat、JNDI - WebSphere MQ
- java - RabbitListenerTestHarness 的问题,它不起作用
- javascript - 递归创建对象时如何保留孩子的父ID?
- node.js - Nodejs 提供多个文件和 JSON 数据
- reactjs - Next.js 基于选中项渲染组件