2015-05-05 2 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) 

Я тестирую положить изображение на случайных но repaint(); координатам не работает правильно. Похоже, что метод paintComponent() запускается после generateFuelStations() конца, а на экране появляется только одно изображение на последних сгенерированных координатах.

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. Вы должны отказаться от метода paintComponent() вместо вызова getGraphics() и обновить с помощью repaint().

0

Документация getGraphics() говорит

Создает графический контекст для этого компонента. Этот метод возвращает null, если этот компонент в настоящее время не отображается.

Ваш класс не отображается, потому что вы не звоните в super() в свой конструктор. Всегда вызывайте конструктор родительского класса при расширении класса.

Примечание: эту часть документации найти было нелегко. Когда вы смотрите на метод, и он говорит, что он переопределяет метод родительского класса, всегда смотрите также на метод родительского класса, потому что часто (читайте: большую часть времени) переопределенный метод будет иметь вызов метода родителя. Выкапывание документации часто дает вам ответ на вопрос, почему ваша программа не работает, хотя не забывайте также время от времени анализировать свой собственный код.

Смежные вопросы