同时绘制分形
Paint fractals simultaneously
我需要用 Threads(实现 Runnable())为大学作业编写 java 代码。我需要同时绘制 4 个分形(使用 thread.sleep())。我已经尝试了几乎我所知道的一切,但这仍然行不通。所以我清理了源。
我有四个类(四个分形)。在我的 JPanel 中,我调用了一个 paint 方法来绘制它们(它们是递归的)。谁能救救我吗?
public class MainPanel extends JPanel {
FractalTree tree = new FractalTree();
FractalCircle circle = new FractalCircle();
FractalSquare square = new FractalSquare();
FractalCircle2 circle2 = new FractalCircle2();
@Override
public void paint(Graphics g) {
setBackground(Color.black,g);
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.WHITE);
DrawBounds(g);
tree.drawTree(g,200,290,-90,9);
circle.drawCircle(g2,675,175,300);
square.drawSquares(g, 200, 525, 100,7);
circle2.drawCircle(g2,675,518,300);
}
public void DrawBounds(Graphics g){
g.drawLine(0,350,900,350);
g.drawLine(450,0,450,700);
}
public void setBackground(Color c,Graphics g){
g.fillRect(0, 0, 900, 700);
}
}
public class FractalSquare{
public void drawSquares(Graphics g,int x, int y, int side ,int size){
g.setColor(Color.BLUE);
if(size >2){
size--;
g.fillRect(x-side/2, y-side/2, side, side);
side = side/2;
x = x-side;
y = y-side;
drawSquares(g,x,y,side,size);
drawSquares(g,x+side*2,y,side,size);
drawSquares(g,x,y+side*2,side,size);
drawSquares(g,x+side*2,y+side*2,side,size);
} else return;
}
}
public class FractalCircle {
public void drawCircle(Graphics2D g, float x, float y, float radius) {
g.setColor(Color.RED);
g.draw(new Ellipse2D.Float(x-radius/2, y-radius/2, radius,radius));
if(radius > 2) {
radius *= 0.75f;
drawCircle(g,x, y, radius);
} else return ;
}
}
public class FractalCircle2 {
public void drawCircle(Graphics2D g, float x, float y, float radius) {
Color color = new Color(255,0,255);
g.setColor(color);
g.draw(new Ellipse2D.Float(x-radius/2, y-radius/2, radius,radius));
if(radius > 1) {
radius *= 0.75f;
drawCircle(g,x + radius/2, y, radius/2);
drawCircle(g,x - radius/2, y, radius/2);
} else return ;
}
}
public class FractalTree {
public void drawTree(Graphics g, int x1, int y1, double angle, int depth) {
g.setColor(Color.GREEN);
if (depth == 0) return;
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 5.0);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 5.0);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 20, depth - 1);
drawTree(g, x2, y2, angle + 20, depth - 1);
}
}
您必须将分形渲染成单独的图像,并在渲染过程中将它们复制到屏幕上。
如果将每个分形包装在 JComponent
中,Swing 将为您完成大部分工作。
这是一个使用您的分形之一的示例:
public class FractalPanel extends JPanel {
final FractalSquare square = new FractalSquare(450, 350);
public FractalPanel() {
add(square);
}
public static void main(String[] args) {
FractalPanel fractalPanel = new FractalPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(fractalPanel);
frame.pack();
frame.setVisible(true);
Thread squareThread = new Thread(() -> {
try {
fractalPanel.square.render();
} catch (InterruptedException e) {
System.err.println("Interrupted");
}
});
squareThread.start();
}
}
class Fractal extends JComponent {
final BufferedImage image;
final Graphics2D offscreenGraphics;
public Fractal(int width, int height) {
setPreferredSize(new Dimension(width, height));
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
offscreenGraphics = image.createGraphics();
}
// Copy the offscreen image to the main graphics context
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
synchronized (image) { // synchronize with the render thread
g2.drawImage(image, 0, 0, null);
}
}
}
class FractalSquare extends Fractal {
public FractalSquare(int width, int height) {
super(width, height);
}
public void render() throws InterruptedException {
drawSquares(getWidth() / 2, getHeight() / 2, 100, 7);
}
public void drawSquares(int x, int y, int side, int size) throws InterruptedException {
// Sleep for 10ms between frames
Thread.sleep(10);
if (size > 2) {
size--;
synchronized (image) { // synchronize with the draw thread
offscreenGraphics.setColor(Color.BLUE);
System.out.printf("Filling [%d, %d, %d, %d]\n", x - side / 2, y - side / 2, side, side);
offscreenGraphics.fillRect(x - side / 2, y - side / 2, side, side);
}
// Tell Swing that we've updated the image and it needs to be redrawn
repaint();
side = side / 2;
x = x - side;
y = y - side;
drawSquares(x, y, side, size);
drawSquares(x + side * 2, y, side, size);
drawSquares(x, y + side * 2, side, size);
drawSquares(x + side * 2, y + side * 2, side, size);
}
}
}
在包含您的 MainPanel
的 JFrame
中,添加此代码(私有 Thread
及其构造函数中某处的实例):
private Thread threadRepaint;
...
threadRepaint = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
yourPanel.repaint();
FractalSquare.decreaseLimit();
FractalCircle.decreaseLimit();
FractalCircle2.decreaseLimit();
FractalTree.decreaseLimit();
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
threadRepaint.start();
这背后的想法是线程必须每秒(1000 毫秒)减少分形的限制。
在每个分形 类 中,您必须将条件更改为类似这样的内容,并添加一个静态变量。这样,您将看到每次迭代的进展。
对于你的FractalSquare
,它会在到达 2:
时停止
private static limit = 10;
...
public static void decreaseLimit() {
if (limit > 2) limit--;
}
...
// Inside your drawSquares method
if (size > limit){
...
} else return;
其他每个分形的想法基本相同:您设置一个上限,该上限会随着时间(线程的每次迭代)而减小。递减限制会产生每次迭代都在递增的错觉。
我需要用 Threads(实现 Runnable())为大学作业编写 java 代码。我需要同时绘制 4 个分形(使用 thread.sleep())。我已经尝试了几乎我所知道的一切,但这仍然行不通。所以我清理了源。
我有四个类(四个分形)。在我的 JPanel 中,我调用了一个 paint 方法来绘制它们(它们是递归的)。谁能救救我吗?
public class MainPanel extends JPanel {
FractalTree tree = new FractalTree();
FractalCircle circle = new FractalCircle();
FractalSquare square = new FractalSquare();
FractalCircle2 circle2 = new FractalCircle2();
@Override
public void paint(Graphics g) {
setBackground(Color.black,g);
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.WHITE);
DrawBounds(g);
tree.drawTree(g,200,290,-90,9);
circle.drawCircle(g2,675,175,300);
square.drawSquares(g, 200, 525, 100,7);
circle2.drawCircle(g2,675,518,300);
}
public void DrawBounds(Graphics g){
g.drawLine(0,350,900,350);
g.drawLine(450,0,450,700);
}
public void setBackground(Color c,Graphics g){
g.fillRect(0, 0, 900, 700);
}
}
public class FractalSquare{
public void drawSquares(Graphics g,int x, int y, int side ,int size){
g.setColor(Color.BLUE);
if(size >2){
size--;
g.fillRect(x-side/2, y-side/2, side, side);
side = side/2;
x = x-side;
y = y-side;
drawSquares(g,x,y,side,size);
drawSquares(g,x+side*2,y,side,size);
drawSquares(g,x,y+side*2,side,size);
drawSquares(g,x+side*2,y+side*2,side,size);
} else return;
}
}
public class FractalCircle {
public void drawCircle(Graphics2D g, float x, float y, float radius) {
g.setColor(Color.RED);
g.draw(new Ellipse2D.Float(x-radius/2, y-radius/2, radius,radius));
if(radius > 2) {
radius *= 0.75f;
drawCircle(g,x, y, radius);
} else return ;
}
}
public class FractalCircle2 {
public void drawCircle(Graphics2D g, float x, float y, float radius) {
Color color = new Color(255,0,255);
g.setColor(color);
g.draw(new Ellipse2D.Float(x-radius/2, y-radius/2, radius,radius));
if(radius > 1) {
radius *= 0.75f;
drawCircle(g,x + radius/2, y, radius/2);
drawCircle(g,x - radius/2, y, radius/2);
} else return ;
}
}
public class FractalTree {
public void drawTree(Graphics g, int x1, int y1, double angle, int depth) {
g.setColor(Color.GREEN);
if (depth == 0) return;
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 5.0);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 5.0);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 20, depth - 1);
drawTree(g, x2, y2, angle + 20, depth - 1);
}
}
您必须将分形渲染成单独的图像,并在渲染过程中将它们复制到屏幕上。
如果将每个分形包装在 JComponent
中,Swing 将为您完成大部分工作。
这是一个使用您的分形之一的示例:
public class FractalPanel extends JPanel {
final FractalSquare square = new FractalSquare(450, 350);
public FractalPanel() {
add(square);
}
public static void main(String[] args) {
FractalPanel fractalPanel = new FractalPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(fractalPanel);
frame.pack();
frame.setVisible(true);
Thread squareThread = new Thread(() -> {
try {
fractalPanel.square.render();
} catch (InterruptedException e) {
System.err.println("Interrupted");
}
});
squareThread.start();
}
}
class Fractal extends JComponent {
final BufferedImage image;
final Graphics2D offscreenGraphics;
public Fractal(int width, int height) {
setPreferredSize(new Dimension(width, height));
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
offscreenGraphics = image.createGraphics();
}
// Copy the offscreen image to the main graphics context
@Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
synchronized (image) { // synchronize with the render thread
g2.drawImage(image, 0, 0, null);
}
}
}
class FractalSquare extends Fractal {
public FractalSquare(int width, int height) {
super(width, height);
}
public void render() throws InterruptedException {
drawSquares(getWidth() / 2, getHeight() / 2, 100, 7);
}
public void drawSquares(int x, int y, int side, int size) throws InterruptedException {
// Sleep for 10ms between frames
Thread.sleep(10);
if (size > 2) {
size--;
synchronized (image) { // synchronize with the draw thread
offscreenGraphics.setColor(Color.BLUE);
System.out.printf("Filling [%d, %d, %d, %d]\n", x - side / 2, y - side / 2, side, side);
offscreenGraphics.fillRect(x - side / 2, y - side / 2, side, side);
}
// Tell Swing that we've updated the image and it needs to be redrawn
repaint();
side = side / 2;
x = x - side;
y = y - side;
drawSquares(x, y, side, size);
drawSquares(x + side * 2, y, side, size);
drawSquares(x, y + side * 2, side, size);
drawSquares(x + side * 2, y + side * 2, side, size);
}
}
}
在包含您的 MainPanel
的 JFrame
中,添加此代码(私有 Thread
及其构造函数中某处的实例):
private Thread threadRepaint;
...
threadRepaint = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
yourPanel.repaint();
FractalSquare.decreaseLimit();
FractalCircle.decreaseLimit();
FractalCircle2.decreaseLimit();
FractalTree.decreaseLimit();
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
threadRepaint.start();
这背后的想法是线程必须每秒(1000 毫秒)减少分形的限制。
在每个分形 类 中,您必须将条件更改为类似这样的内容,并添加一个静态变量。这样,您将看到每次迭代的进展。
对于你的FractalSquare
,它会在到达 2:
private static limit = 10;
...
public static void decreaseLimit() {
if (limit > 2) limit--;
}
...
// Inside your drawSquares method
if (size > limit){
...
} else return;
其他每个分形的想法基本相同:您设置一个上限,该上限会随着时间(线程的每次迭代)而减小。递减限制会产生每次迭代都在递增的错觉。