我一直在寻找这个答案两天,但这似乎没有解决太多.主要是因为我并不真正了解导致我的错误的原因,也不知道如何解决问题.
我一直试图制作各种各样的“动画”,其中一个图层在屏幕右侧产生圆圈并随着时间的推移将它们发送到左侧.问题是每次它是要产生一个圆圈,它不会出现,我得到一个错误.
Exception in thread "Thread-4" java.lang.NullPointerException
at Ball.draw(Ball.java:39)
at Ball.run(Ball.java:23)
以下是导致错误的类:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class Ball extends Thread{
JPanel drawingPanel;
private int x=400,y=200;
private int dx=-2,dy=0;
private static final int XSIZE=10,YSIZE=10;
Random rdm = new Random();
int y_rdm = rdm.nextInt(440)+30;
public Ball(JPanel jp){
drawingPanel=jp;
dx-=1;
}
public void run(){
draw();
for (int i=0;i<1000;i++){
try{
Thread.sleep(10);
}
catch(InterruptedException e){}
move();
}
}
private void move(){
erase();
changePos();
draw();
}
private void draw(){
Graphics g = drawingPanel.getGraphics();
g.setColor(Color.WHITE);
g.fillOval(x,y_rdm,XSIZE,YSIZE);
g.dispose();
}
private void erase(){
Graphics g=drawingPanel.getGraphics();
g.setColor(drawingPanel.getBackground());
g.fillOval(x,y_rdm,XSIZE,YSIZE);
g.dispose();
}
private void changePos(){
x+=dx;y_rdm+=dy;
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BallPanel extends JPanel implements ActionListener{
JPanel drawingPanel = new JPanel();
public BallPanel(){
int delay = 300;
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
Ball b= new Ball(drawingPanel);
b.start();
}
};
new Timer(delay, taskPerformer).start();
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.io.InputStream;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javazoom.jl.player.Player;
public class Window extends JFrame{
private JLayeredPane layerpane;
private JPanel up, down;
public Window(){
layerpane = new JLayeredPane();
down = new JPanel();
down.setBounds(0, 0, 450, 450);
down.setBackground(new Color(0, 51, 102));
layerpane.add(down, new Integer(1));
BallPanel bp = new BallPanel();
layerpane.add(bp, new Integer(2));
bp.setBounds(0, 0, 450, 450);
bp.setOpaque(!bp.isOpaque());
Animation2 ani2 = new Ani2();
ani2.setBounds(0, 0, 400, 450);
layerpane.add(ani2, new Integer(3));
ani2.setOpaque(!ani2.isOpaque());
getContentPane().add(layerpane, BorderLayout.CENTER);
}
public static void main(String args[]){
JFrame f = new Window();
f.setVisible(true);
f.setSize(450,450);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{
URL url = new URL("file:///C://song.mp3");
InputStream in = url.openStream();
Player pl = new Player(in);
pl.play();
}
catch(Exception e){
e.printStackTrace();
}
}
}
请告诉我,如果我需要包括我的其他课程,他们似乎有点无关紧要.
解决方法:
JComponent的getGraphics方法返回与Component关联的Graphics对象.但是如果没有关联的Graphics对象,它将返回null,这在您的代码中就是这种情况.
只有将Component添加到与其关联的容器中,或者如果它是*容器(JFrame,JDialog和JApplet)时,Component才与Graphics对象关联.
您的问题是您的JPanel不包含在任何*容器中,因此其关联的Graphics对象为null.
要解决此问题,请确保在对其调用getGraphics()之前将JPanel添加到*容器,或者改为扩展JPanel并覆盖其paintComponent(Graphics g)方法以执行绘制(第二个选项是首选因为每当需要重绘父容器时都会自动调用paintComponent方法(例如,如果它被调整大小,或被其他窗口阻塞和解除阻塞,……)).
(顺便说一句,在你的BallPanel类中扩展JPanel,你定义一个新的JPanel并将它传递给Ball的构造函数.你应该将它传递给构造函数,因为drawingPanel永远不会添加到任何容器,但是BallPanel实例本身在一个类中定义一个JPanel字段真的没有意义,该类本身就是一个JPanel,并且该字段完成了该类本身应该做的工作.)