异常的线程,java.lang.NullPointerException

时间:2021-09-23 10:54:42

I have been searching for an answer to this for two days now, but that didn't seem to solve much. Mostly because i don't really understand what is causing my error in the first place, nor would i know how to go about fixing the problem.

我已经找了两天的答案了,但这似乎解决不了什么问题。主要是因为我一开始就不知道是什么导致了我的错误,我也不知道如何着手解决这个问题。

I've been trying to make an "animation" of sorts, where one of the layers in it spawn circles on the right side of the screen and send them to the left over time. Problem is every time it is meant to spawn a circle, it doesn't appear and i get an error.

我一直在尝试制作一种“动画”,其中的一层在屏幕的右边产生圆圈,随着时间的推移将它们发送到左边。问题是每次它要产生一个圆,它不会出现,我就会得到一个错误。

Exception in thread "Thread-4" java.lang.NullPointerException
at Ball.draw(Ball.java:39)
at Ball.run(Ball.java:23)

Here is the class that is causing the errors:

这是导致错误的类:

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


        }

    }

Please tell me if i need to include my other classes, they just seem slightly irrelevant.

请告诉我,如果我需要我的其他课程,他们似乎有点不相关。

1 个解决方案

#1


5  

The getGraphics method of JComponent returns the Graphics object associated with the Component. But if there is no Graphics object associated it will return null, which is the case in your code.

JComponent的getGraphics方法返回与组件相关联的图形对象。但是如果没有图形对象关联,它将返回null,这是代码中的情况。

A Component is associated with a Graphics object only when it is added to a container that is associated with one, or if it is a Top-Level Container (JFrame, JDialog, and JApplet).

只有当组件被添加到与之关联的容器中时,或者如果它是*容器(JFrame, JDialog和JApplet),它才与图形对象相关联。

Your problem here is that your JPanel is not contained inside any top-level container, so its associated Graphics object is null.

这里的问题是,JPanel不包含在任何*容器中,因此它的关联图形对象为null。

To fix the problem, either make sure you have added the JPanel to a top-level container before you call getGraphics() on it, or instead extend JPanel and override its paintComponent(Graphics g) method to do the drawing (second option is preferred since the paintComponent method is called automatically whenever the parent container needs to be redrawn (e.g. if it was resized, or blocked and unblocked by some other window, ...)).

来解决这个问题,确保你有添加的JPanel*容器之前你叫getGraphics(),或相反延长JPanel,覆盖其paintComponent(图形g)的方法来完成绘画(paintComponent以来第二个选项是首选方法被称为自动当父容器需要重绘(如如果是大小,或阻塞和畅通无阻的其他窗口,…))。

(By the way, in your BallPanel class which extends JPanel, you define a new JPanel and pass it to Ball's constructor. You should be passing this to the the constructor, since the drawingPanel is never added to any container, but the BallPanel instance itself is. It really doesn't make sense to define a JPanel field inside a class which is itself a JPanel and have the field do the job that the class itself is supposed to do.)

顺便说一下,在扩展JPanel的BallPanel类中,您定义了一个新的JPanel并将其传递给Ball的构造函数。您应该将它传递给构造函数,因为不会将drawingPanel添加到任何容器中,但是BallPanel实例本身就是这样的。在一个类中定义一个JPanel字段是没有意义的,它本身就是一个JPanel,让这个字段做类本身应该做的工作)

#1


5  

The getGraphics method of JComponent returns the Graphics object associated with the Component. But if there is no Graphics object associated it will return null, which is the case in your code.

JComponent的getGraphics方法返回与组件相关联的图形对象。但是如果没有图形对象关联,它将返回null,这是代码中的情况。

A Component is associated with a Graphics object only when it is added to a container that is associated with one, or if it is a Top-Level Container (JFrame, JDialog, and JApplet).

只有当组件被添加到与之关联的容器中时,或者如果它是*容器(JFrame, JDialog和JApplet),它才与图形对象相关联。

Your problem here is that your JPanel is not contained inside any top-level container, so its associated Graphics object is null.

这里的问题是,JPanel不包含在任何*容器中,因此它的关联图形对象为null。

To fix the problem, either make sure you have added the JPanel to a top-level container before you call getGraphics() on it, or instead extend JPanel and override its paintComponent(Graphics g) method to do the drawing (second option is preferred since the paintComponent method is called automatically whenever the parent container needs to be redrawn (e.g. if it was resized, or blocked and unblocked by some other window, ...)).

来解决这个问题,确保你有添加的JPanel*容器之前你叫getGraphics(),或相反延长JPanel,覆盖其paintComponent(图形g)的方法来完成绘画(paintComponent以来第二个选项是首选方法被称为自动当父容器需要重绘(如如果是大小,或阻塞和畅通无阻的其他窗口,…))。

(By the way, in your BallPanel class which extends JPanel, you define a new JPanel and pass it to Ball's constructor. You should be passing this to the the constructor, since the drawingPanel is never added to any container, but the BallPanel instance itself is. It really doesn't make sense to define a JPanel field inside a class which is itself a JPanel and have the field do the job that the class itself is supposed to do.)

顺便说一下,在扩展JPanel的BallPanel类中,您定义了一个新的JPanel并将其传递给Ball的构造函数。您应该将它传递给构造函数,因为不会将drawingPanel添加到任何容器中,但是BallPanel实例本身就是这样的。在一个类中定义一个JPanel字段是没有意义的,它本身就是一个JPanel,让这个字段做类本身应该做的工作)