为什么我的笔触粗细会发生变化?
Why is my brushstroke thickness changing?
我的任务是绘制随机宽度和随机线条粗细的水平线。当我 运行 我的程序时,厚度在中途发生变化。我不明白这是怎么可能的,因为我先设置宽度然后画线。我不更新,所以据我所知我不会重新画线。程序中唯一的其他代码是我们必须在小程序中执行的 init()。
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
int increment = 70; // space between lines
int linesNum = 5; // number of lines were drawing
Random rand = new Random();
int randW;
Line2D.Float[] lines = new Line2D.Float[linesNum];
for (int y = 0; y < linesNum; y++) {
// where we are at on they axis
int yoffset = (increment * y) + increment;
// random width of line max 499 min 50
randW = rand.nextInt((499 - 5) + 1) + 5;
// random thick line
g2.setStroke(new BasicStroke(rand.nextInt((increment - 10) + 1) + 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
lines[y] = new Line2D.Float(1, yoffset, randW, yoffset);
g2.draw(lines[y]);
}
}
}
每次重绘小程序,这可能是由于 window 移动、最小化和恢复,或被另一个 window 遮挡然后显示,paint
方法将再次调用,因此将创建一个 new Random()
并以新的随机粗细重新绘制线条。如果您不希望这种情况发生,可以采取一些方法。
离屏缓冲区
您可以使用 createImage
方法创建一个缓冲区来绘制线条。使用其 getGraphics
方法获取 Graphics
对象,绘制线条,然后在您的 paint
方法中使用 drawImage
方法在屏幕上绘制此缓冲区 Graphics
传递给 paint
的对象。将屏幕外缓冲区声明为您的小程序的一个字段 class。因为您只会在缓冲区上绘制一次,所以您的 applet 被重新绘制多少次并不重要。
随机数数组
您的 paint
方法中有两个地方调用了 rand.nextInt
;您可以创建两个大小为 linesNum
的 int[]
数组,将它们声明为小程序的字段,然后使用 Random
对象将它们填充到 init
方法中。然后,在您的 paint
方法中,不是生成随机数,而是重复使用您之前存储在这些数组中的随机数。这样,无论你的小程序重绘多少次,你都会得到相同的结果。
为随机数生成器播种
在您的 paint
方法中,您创建了一个 new Random()
对象。您可以通过调用将种子作为参数的构造函数或调用其上的 setSeed
方法来为随机数生成器 (RNG) 设定种子。如果您使用相同的种子,您将始终获得相同的伪随机数序列。如果您希望小程序的每个 运行 具有不同的随机线宽(但不是让它们在每次重绘时改变),您可以创建一个 Random
对象并使用其 nextLong
方法来当您的小程序启动时选择一个随机种子,将该种子存储在您的小程序 class 的字段中,然后使用它在您的 paint
方法中为 RNG 播种。这样,每次调用 paint
时都会得到相同的随机数序列。
我的任务是绘制随机宽度和随机线条粗细的水平线。当我 运行 我的程序时,厚度在中途发生变化。我不明白这是怎么可能的,因为我先设置宽度然后画线。我不更新,所以据我所知我不会重新画线。程序中唯一的其他代码是我们必须在小程序中执行的 init()。
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
int increment = 70; // space between lines
int linesNum = 5; // number of lines were drawing
Random rand = new Random();
int randW;
Line2D.Float[] lines = new Line2D.Float[linesNum];
for (int y = 0; y < linesNum; y++) {
// where we are at on they axis
int yoffset = (increment * y) + increment;
// random width of line max 499 min 50
randW = rand.nextInt((499 - 5) + 1) + 5;
// random thick line
g2.setStroke(new BasicStroke(rand.nextInt((increment - 10) + 1) + 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
lines[y] = new Line2D.Float(1, yoffset, randW, yoffset);
g2.draw(lines[y]);
}
}
}
每次重绘小程序,这可能是由于 window 移动、最小化和恢复,或被另一个 window 遮挡然后显示,paint
方法将再次调用,因此将创建一个 new Random()
并以新的随机粗细重新绘制线条。如果您不希望这种情况发生,可以采取一些方法。
离屏缓冲区
您可以使用 createImage
方法创建一个缓冲区来绘制线条。使用其 getGraphics
方法获取 Graphics
对象,绘制线条,然后在您的 paint
方法中使用 drawImage
方法在屏幕上绘制此缓冲区 Graphics
传递给 paint
的对象。将屏幕外缓冲区声明为您的小程序的一个字段 class。因为您只会在缓冲区上绘制一次,所以您的 applet 被重新绘制多少次并不重要。
随机数数组
您的 paint
方法中有两个地方调用了 rand.nextInt
;您可以创建两个大小为 linesNum
的 int[]
数组,将它们声明为小程序的字段,然后使用 Random
对象将它们填充到 init
方法中。然后,在您的 paint
方法中,不是生成随机数,而是重复使用您之前存储在这些数组中的随机数。这样,无论你的小程序重绘多少次,你都会得到相同的结果。
为随机数生成器播种
在您的 paint
方法中,您创建了一个 new Random()
对象。您可以通过调用将种子作为参数的构造函数或调用其上的 setSeed
方法来为随机数生成器 (RNG) 设定种子。如果您使用相同的种子,您将始终获得相同的伪随机数序列。如果您希望小程序的每个 运行 具有不同的随机线宽(但不是让它们在每次重绘时改变),您可以创建一个 Random
对象并使用其 nextLong
方法来当您的小程序启动时选择一个随机种子,将该种子存储在您的小程序 class 的字段中,然后使用它在您的 paint
方法中为 RNG 播种。这样,每次调用 paint
时都会得到相同的随机数序列。