我正在写一个游戏,当我试图绘制一个篮子对象时,得到一个空指针异常,即使我在主游戏构造函数中创建了篮子,在最终绘制篮子的计时器开始之前。唯一涉及到这一行错误的其他对象是paint组件的图形对象,但我用print语句检查了一下,那也不是null。奇怪的是,即使我在绘制篮子的那一行出现了异常,篮子的图像仍然显示在帧上,但当我按下移动它的键时,却没有更新(移动)。这里是游戏主类、篮筐类和完整的栈跟踪。
import java.awt.*;
import javax.swing.*;
import java.util.Collections;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.event.*;
import java.util.ArrayList;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class MainGame extends JPanel {
JFrame frame;
ArrayList<Ball> balls;
Basket basket;
int score;
int level;
Timer timer;
public MainGame() {
addKeyListener(new TAdapter());
setFocusable(true);
frame = new JFrame("Drop catch");
frame.setSize(800, 800);
frame.setBackground(Color.BLUE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
this.setBackground(Color.BLUE);
frame.getContentPane().add(this);
//frame.getContentPane().add(textField);
frame.setVisible(true);
balls = new ArrayList<Ball>();
basket = new Basket(frame.getWidth() / 2, frame.getHeight() * 2 / 3);
timer = new Timer(20, new TimerListener());
timer.start();
}
public static void main(String[] args) {
MainGame myMainGame = new MainGame();
}
public void drawScore(Graphics g) {
g.drawString(String.valueOf(score), frame.getWidth() / 10, frame.getHeight() / 10);
}
public void updateScore() {
//might want something like this
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(Ball b : balls) {
b.draw(g);
}
boolean test = g == null || basket == null;
System.out.println(test);//this prints false, so basket and g are both not null
basket.draw(g);//this is line 57, where the exception is
drawScore(g);
}
public class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
for(Ball b : balls) {
b.update();
}
basket.update();
updateScore();
frame.repaint();
}
}
private class TAdapter extends KeyAdapter {
@Override
public void keyReleased(KeyEvent e) {
System.out.println("Key released");
basket.keyReleased(e);
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println("Key pressed");
basket.keyPressed(e);
}
}
}
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Graphics;
import java.io.File;
public class Basket {
int x;
int y;
int vel;
BufferedImage sprite;
public Basket(int x_, int y_) {
x = x_;
y = y_;
importImage();
}
public void importImage() {
File imageFile = new File("sprites/basket.jpg");
try {
sprite =ImageIO.read(imageFile);
} catch(Exception e) {e.printStackTrace();}
}
public void update() {
x += vel;
}
public void draw(Graphics g) {
g.drawImage(sprite, x, y, null);
}
//movement stuff
//public class movementListener implements KeyListener {
public void keyPressed(KeyEvent e) {
if(e.equals(KeyEvent.VK_KP_LEFT) || e.equals(KeyEvent.VK_A)) {
vel = -1;
}
if(e.equals(KeyEvent.VK_KP_RIGHT) || e.equals(KeyEvent.VK_D)) {
vel = 1;
}
System.out.println("Key pressed in basket");
}
public void keyReleased(KeyEvent e) {
vel = 0;
System.out.println("Key released in basket");
}
public void keyTyped(KeyEvent e) {}
//}
}
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at MainGame.paintComponent(MainGame.java:57)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5262)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedFPScales(RepaintManager.java:1707)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1616)
at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1060)
at java.desktop/java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
at java.desktop/sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:75)
at java.desktop/sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:112)
at java.desktop/java.awt.Container.paint(Container.java:2002)
at java.desktop/java.awt.Window.paint(Window.java:3928)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:876)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:316)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
首先,你的测试条件是错误的,它给你false,因为图形对象不是null。如果你想检查两个对象使用&&。
test = grap != null && basket=!null;
其次,你不知道Swing的生命周期,你调用了 frame.getContentPane().add(this);
在您启动篮子和 frame.getContentPane().add(this);
在篮子被初始化之前调用draw。我不想知道你的代码是怎么做的,但最简单的解决方案是在你将组件添加到框架中之前初始化Basket。
public MainGame() {
addKeyListener(new TAdapter());
setFocusable(true);
frame = new JFrame("Drop catch");
frame.setSize(800, 800);
frame.setBackground(Color.BLUE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
this.setBackground(Color.BLUE);
basket = new Basket(frame.getWidth() / 2, frame.getHeight() * 2 / 3);//init before add
frame.getContentPane().add(this);
//frame.getContentPane().add(textField);
frame.setVisible(true);
timer = new Timer(20, new TimerListener());
timer.start();
}