我想在一段时间延迟后在生成的坐标上绘制图像,但我得到了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);
}
}
答案 0 :(得分:3)
不要将Thread用于动画。相反,你应该使用Swing Timer。然后,当Timer触发时,调整要移动的图像的属性(x1 / y1,x2,y2)值,并在组件上调用repaint()
。这些属性应该是类的属性。
不要使用getGraphics()。通过覆盖paintComponent()
方法完成自定义绘制,然后使用传递给方法的Graphics对象进行自定义绘制。基本上,我认为,您的paintComponent()
方法应该调用您的drawLine(...)
方法。
答案 1 :(得分:0)
似乎你的getGraphics()调用返回null。你应该ovverride paintComponent()方法而不是调用getGraphics()并使用repaint()更新。
答案 2 :(得分:0)
getGraphics()
的文档说
为此组件创建图形上下文。如果此组件当前不可显示,则此方法将返回null。
您的课程无法显示,因为您未在构造函数中调用super()
。在扩展类时,始终调用父类的构造函数。
注意:文档的这一特定部分并不容易找到。当你查看一个方法并且它说它覆盖了父类的方法时,总是要查看父类的方法,因为经常(读取:大部分时间)被覆盖的方法将调用父类的方法。通过文档挖掘通常可以帮助您解决程序无法正常工作的原因,但也不要忘记同时仔细检查自己的代码。