2015-05-05 67 views
0

我想在一段时间延迟后在生成的坐标上绘制图像,但我得到了nullpointerexception。我试图让我的形象从一个点移动到另一个点,并且有明显的时间延迟。带时间延迟的绘图图像

public class PaintStations extends JPanel implements Runnable { 

    private static final long serialVersionUID = 6734649580151111907L; 
    private Thread thread; 

    public PaintStations() { 
     setSize(new Dimension(MainWindow.WIDTH, MainWindow.HEIGHT)); 
     setOpaque(false); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
    } 

    private void plot(Graphics g, int x, int y) { 
     Graphics2D g2d = (Graphics2D) g; 
     Image img = Toolkit.getDefaultToolkit().getImage("cpn.png"); 
     g2d.drawImage(img, x, y, this); 
    } 

    private void drawLine(Graphics g, int x1, int y1, int x2, int y2) { 
     int d = 0; 

     int dy = Math.abs(y2 - y1); 
     int dx = Math.abs(x2 - x1); 

     int dy2 = (dy << 1); 
     int dx2 = (dx << 1); 

     int ix = x1 < x2 ? 1 : -1; 
     int iy = y1 < y2 ? 1 : -1; 

     if (dy <= dx) { 
      for (;;) { 
       plot(g, x1, y1); 
       if (x1 == x2) 
        break; 
       x1 += ix; 
       d += dy2; 
       if (d > dx) { 
        y1 += iy; 
        d -= dx2; 
       } 
      } 
     } else { 
      for (;;) { 
       plot(g, x1, y1); 
       if (y1 == y2) 
        break; 
       y1 += iy; 
       d += dx2; 
       if (d > dy) { 
        x1 += ix; 
        d -= dy2; 
       } 
      } 
     } 
    } 

    @Override 
    public void run() { 
     drawLine(getGraphics(), 0, 0, 10, 10); 
    } 

    public void start() { 
     thread = new Thread(this); 
     thread.start(); 
    } 
} 

这里是错误,我得到:

Exception in thread "Thread-1" java.lang.NullPointerException 
    at PaintStations.plot(PaintStations.java:27) 
    at PaintStations.drawLine(PaintStations.java:44) 
    at PaintStations.run(PaintStations.java:71) 
    at java.lang.Thread.run(Unknown Source) 

我测试将图像随机COORDS但repaint();无法正常工作。在generateFuelStations()结束后,似乎paintComponent()方法被触发,并且在屏幕上只在最后生成的坐标上出现一个图像。

public class PaintStations extends JPanel implements Runnable { 

    private static final long serialVersionUID = 6734649580151111907L; 
    private ArrayList<Point> stationsLocation; 
    private Shape region; 
    private int x; 
    private int y; 
    private int stationsNumber; 

    public PaintStations(Shape region, int stationsNumber) { 
     setSize(new Dimension(MainWindow.WIDTH, MainWindow.HEIGHT)); 
     setOpaque(false); 
     this.region = region; 
     this.stationsNumber = stationsNumber; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     System.out.println("Repaint!"); 
     Graphics2D g2d = (Graphics2D) g; 
     Image img = Toolkit.getDefaultToolkit().getImage("cpn.png"); 
     g2d.drawImage(img, x, y, this); 
    } 

    private void generateFuelStations(int stationsNumber) { 
     Rectangle r = region.getBounds(); 
     this.stationsLocation = new ArrayList<>(); 

     for(int i=0; i<stationsNumber; i++) { 
      Random rand = new Random(); 

      do { 
       x = (int) (r.getX() + rand.nextInt((int) r.getWidth())); 
       y = (int) (r.getY() + rand.nextInt((int) r.getHeight())); 
      } while(!region.contains(x,y)); 
      System.out.println("X: " + x + " Y: " + y); 
      stationsLocation.add(new Point(x,y)); 
      repaint(); 
     } 
    } 

    @Override 
    public void run() { 
     generateFuelStations(stationsNumber); 
    } 
} 

回答

3

不要使用线程进行动画。相反,你应该使用Swing Timer。然后,当定时器启动时,调整要移动的图像的属性(x1/y1,x2,y2)值,并在组件上调用repaint()。这些属性应该是该类的属性。

请勿使用getGraphics()。自定义绘画是通过覆盖paintComponent()方法完成的,然后使用传递给自定义绘画方法的Graphics对象。所以基本上,我认为,你的paintComponent()方法应该调用你的drawLine(...)方法。

+0

@Tavo,谢谢... – camickr

0

好像你的getGraphics()调用返回null。您应该ovverride paintComponent()方法而不是调用getGraphics()并使用repaint()更新。

0

getGraphics()文档说

为组件创建一个图形上下文。如果此组件当前不可显示,则此方法将返回null。

由于您在构造函数中没有调用super(),所以您的类不可显示。扩展一个类时,总是要调用父类的构造函数。

注意:文档的这个特定部分不容易找到。当你查看一个方法并且它说它覆盖了一个父类的方法时,总是要查看父类的方法,因为经常(读:大多数时候)重写的方法将会调用父方法。通过文档挖掘通常会给你一个答案,说明为什么你的程序不工作,但不要忘记也不时仔细检查你自己的代码。