我想在一段时间延迟后在生成的坐标上绘制图像,但是我得到了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);
}
}
不要使用线程进行动画。相反,您应该使用摆动计时器。然后,当计时器启动时,您要调整要移动并在组件上调用repaint()
的图像的属性(x1/y1,x2,y2)。这些属性应该是类的属性。
不要使用getGraphics()。自定义绘画是通过覆盖paintComponent()
方法来完成的,然后使用传递给自定义绘画方法的图形对象。因此,基本上,我认为,您的paintComponent()
方法应调用您的drawLine(...)
方法。
似乎是您的getGraphics()调用返回null。您应该ovverride the PaintComponent()方法,而不是调用getGraphics(),然后使用Repaver()。
getGraphics()
的文档说
为此组件创建图形上下文。如果此组件当前无法显示,则此方法将返回null。
您的班级无法显示,因为您在构造函数中不致电super()
。扩展课程时,请始终致电父类的构造函数。
注意:文档的这个特定部分并不容易找到。当您查看一种方法并说它覆盖了父类方法时,请始终查看父类的方法,因为通常(阅读:大部分时间)被覆盖的方法会呼叫父母的方法。挖掘文档通常会给您一个答案,以解决为什么您的程序不起作用,尽管不要忘记也不时仔细检查自己的代码。