2015-05-05 102 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(),所以您的類不可顯示。擴展一個類時,總是要調用父類的構造函數。

注意:文檔的這個特定部分不容易找到。當你查看一個方法並且它說它覆蓋了一個父類的方法時,總是要查看父類的方法,因爲經常(讀:大多數時候)重寫的方法將會調用父方法。通過文檔挖掘通常會給你一個答案,說明爲什麼你的程序不工作,但不要忘記也不時仔細檢查你自己的代碼。