patternjavaMinor
Creation of Queen Ann's Lace fractal
Viewed 0 times
fractalqueenanncreationlace
Problem
I've created a program which recreates the Queen Ann's Lace fractal. However, when the amount of points that are being plotted increases, the points are plotted way slower. Is there any way to make it so that I only add a point, instead of adding a point and repainting all of the others? I've looked everywhere for an answer, and nothing has made sense to me. An explanation would be very helpful.
```
import javax.swing.*; //JFrame and JPanel
import java.awt.*; //Color and Container
import javax.swing.JOptionPane;
import java.awt.event.*;
import java.util.Scanner;
import java.io.*;
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
/**
* Write a description of class ChaosGame here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class QueensLaceFractal
{
public static void main(String[] args) { //main method
Dimension d = new Dimension(700, 700);
JFrame theGUI = new JFrame("Queens Lace Fractal");
ColorPanel panel = new ColorPanel(Color.white);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(d);
Container pane = theGUI.getContentPane();
pane.add(panel);
theGUI.pack();
theGUI.setVisible(true);
}
}
class ColorPanel extends JPanel implements MouseMotionListener, MouseListener{ //colorpanel class
private boolean followMouse = true;
private int x, y;
private int seedx, seedy;
private int pointx, pointy;
private int i;
private int dotcounter;
private int newx, newy;
private Random random = new Random();
private javax.swing.Timer timer;
private javax.swing.Timer arraytimer;
private EndPoint[] EP = new EndPoint[8];
private Seed seed;
private Point[] p = new Point[50000];
private Color yellow = new Color(255, 255, 1);
private Color yellowOrange = new Color(255, 195, 0);
private Color orangeRed = new Color(255, 83, 0);
private Color violetRed =
```
import javax.swing.*; //JFrame and JPanel
import java.awt.*; //Color and Container
import javax.swing.JOptionPane;
import java.awt.event.*;
import java.util.Scanner;
import java.io.*;
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
/**
* Write a description of class ChaosGame here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class QueensLaceFractal
{
public static void main(String[] args) { //main method
Dimension d = new Dimension(700, 700);
JFrame theGUI = new JFrame("Queens Lace Fractal");
ColorPanel panel = new ColorPanel(Color.white);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(d);
Container pane = theGUI.getContentPane();
pane.add(panel);
theGUI.pack();
theGUI.setVisible(true);
}
}
class ColorPanel extends JPanel implements MouseMotionListener, MouseListener{ //colorpanel class
private boolean followMouse = true;
private int x, y;
private int seedx, seedy;
private int pointx, pointy;
private int i;
private int dotcounter;
private int newx, newy;
private Random random = new Random();
private javax.swing.Timer timer;
private javax.swing.Timer arraytimer;
private EndPoint[] EP = new EndPoint[8];
private Seed seed;
private Point[] p = new Point[50000];
private Color yellow = new Color(255, 255, 1);
private Color yellowOrange = new Color(255, 195, 0);
private Color orangeRed = new Color(255, 83, 0);
private Color violetRed =
Solution
The reason your current code will eventually slow down is because you are drawing every previously calculated pixel, every millisecond. So towards the end of your drawing, you're trying to plot 500,000 pixels in every
To fix this, create yourself a transparent buffered image which you will paint your pixels onto. Then, in your repaint method, you can:
Here's a modified version of your code that does exactly that. I also made a few edits along the way, some of which I'm afraid I've forgotten as I chased after the main prize. However, here's a few things I changed:
Here's the final code:
```
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension; //Color and Container
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame; //JFrame and JPanel
import javax.swing.JPanel;
import javax.swing.Timer;
/**
* Write a description of class ChaosGame here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class QueensLaceFractal {
public static void main(String[] args) { // main method
Dimension d = new Dimension(700, 700);
JFrame theGUI = new JFrame("Queens Lace Fractal");
ColorPanel panel = new ColorPanel(Color.white);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(d);
Container pane = theGUI.getContentPane();
pane.add(panel);
theGUI.pack();
// Must be called after pack() so that size of panel is known
panel.startRendering();
theGUI.setVisible(true);
}
}
class ColorPanel extends JPanel {
private static final long serialVersionUID = 1L;
private boolean followMouse = true;
private int x, y;
private int seedx, seedy;
private int pointx, pointy;
private int dotcounter = 1;
private int newx, newy;
private Random random = new Random();
private javax.swing.Timer timer;
private EndPoint[] EP = new EndPoint[8];
private Seed seed;
private Color yellow = new Color(255, 255, 1);
private Color yellowOrange = new Color(255, 195, 0);
private Color orangeRed = new Color(255, 83, 0);
private Color violetRed = new Color(215, 0, 46);
private Color violet = new Color(129, 0, 127);
private Color violetBlue = new Color(44, 48, 156);
private Color blueGreen = new Color(0, 101, 87);
private Color yellowGreen = new Color(85, 171, 0);
private BufferedImage fractalImage;
public ColorPanel(Color backcolor) {
setBackground(backcolor);
setDoubleBuffered(true);
// constructor
addMouseListener(new SeedMouseListener());
addMouseMotionListener(new SeedMouseMotionListener());
this.setFocusable(true);
seed = new Seed(350, 350, Color.BLACK);
EP[0] = new EndPoint(350, 50, yellow);
EP[1] = new EndPoint(562, 138, yellowOrange);
EP[2] = new EndPoint(650, 350, orangeRed);
EP[3] = new EndPoint(562, 562, violetRed);
EP[4] = new EndPoint(350, 650, violet);
EP[5] = new EndPoint(138, 562, violetBlue);
EP[6] = new EndPoint(50, 350, blueGreen);
EP[7] = new EndPoint(138, 138, yellowGreen);
}
public void startRendering() {
// Create a buffered image to hold the fractal. Make the background
// transparent
fractalImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = fractalImage.createGraphics();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
timer = new Timer(1, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
private class SeedMouseMotionListener extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
// gets x and y of the mouse at all times
x = e.getX();
y = e.getY();
}
}
private class SeedMouseListener extends MouseAdapter {
@Override
public void mouseMoved(MouseEvent e) {
// gets x and y of the mouse at all times
x = e.getX();
y = e.ge
paintComponent invocation.To fix this, create yourself a transparent buffered image which you will paint your pixels onto. Then, in your repaint method, you can:
- wipe the panel
- paint your seed image
- paint the coloured circles
- add one more dot to your buffered image
- paint the buffered image on top
Here's a modified version of your code that does exactly that. I also made a few edits along the way, some of which I'm afraid I've forgotten as I chased after the main prize. However, here's a few things I changed:
- Used adaptor classes rather than implementing the mouse listeners in the panel itself. The adaptor classes (
MouseAdapterandMouseMotionAdapter) conveniently have empty implementations for all methods in the equivalent listener interfaces.
- No need to do
if(foo == true). It should just beif (foo). There is also no need for emptyelse{}clauses; they can be removed.
Here's the final code:
```
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension; //Color and Container
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame; //JFrame and JPanel
import javax.swing.JPanel;
import javax.swing.Timer;
/**
* Write a description of class ChaosGame here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class QueensLaceFractal {
public static void main(String[] args) { // main method
Dimension d = new Dimension(700, 700);
JFrame theGUI = new JFrame("Queens Lace Fractal");
ColorPanel panel = new ColorPanel(Color.white);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(d);
Container pane = theGUI.getContentPane();
pane.add(panel);
theGUI.pack();
// Must be called after pack() so that size of panel is known
panel.startRendering();
theGUI.setVisible(true);
}
}
class ColorPanel extends JPanel {
private static final long serialVersionUID = 1L;
private boolean followMouse = true;
private int x, y;
private int seedx, seedy;
private int pointx, pointy;
private int dotcounter = 1;
private int newx, newy;
private Random random = new Random();
private javax.swing.Timer timer;
private EndPoint[] EP = new EndPoint[8];
private Seed seed;
private Color yellow = new Color(255, 255, 1);
private Color yellowOrange = new Color(255, 195, 0);
private Color orangeRed = new Color(255, 83, 0);
private Color violetRed = new Color(215, 0, 46);
private Color violet = new Color(129, 0, 127);
private Color violetBlue = new Color(44, 48, 156);
private Color blueGreen = new Color(0, 101, 87);
private Color yellowGreen = new Color(85, 171, 0);
private BufferedImage fractalImage;
public ColorPanel(Color backcolor) {
setBackground(backcolor);
setDoubleBuffered(true);
// constructor
addMouseListener(new SeedMouseListener());
addMouseMotionListener(new SeedMouseMotionListener());
this.setFocusable(true);
seed = new Seed(350, 350, Color.BLACK);
EP[0] = new EndPoint(350, 50, yellow);
EP[1] = new EndPoint(562, 138, yellowOrange);
EP[2] = new EndPoint(650, 350, orangeRed);
EP[3] = new EndPoint(562, 562, violetRed);
EP[4] = new EndPoint(350, 650, violet);
EP[5] = new EndPoint(138, 562, violetBlue);
EP[6] = new EndPoint(50, 350, blueGreen);
EP[7] = new EndPoint(138, 138, yellowGreen);
}
public void startRendering() {
// Create a buffered image to hold the fractal. Make the background
// transparent
fractalImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = fractalImage.createGraphics();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
timer = new Timer(1, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
private class SeedMouseMotionListener extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
// gets x and y of the mouse at all times
x = e.getX();
y = e.getY();
}
}
private class SeedMouseListener extends MouseAdapter {
@Override
public void mouseMoved(MouseEvent e) {
// gets x and y of the mouse at all times
x = e.getX();
y = e.ge
Code Snippets
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension; //Color and Container
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame; //JFrame and JPanel
import javax.swing.JPanel;
import javax.swing.Timer;
/**
* Write a description of class ChaosGame here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class QueensLaceFractal {
public static void main(String[] args) { // main method
Dimension d = new Dimension(700, 700);
JFrame theGUI = new JFrame("Queens Lace Fractal");
ColorPanel panel = new ColorPanel(Color.white);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(d);
Container pane = theGUI.getContentPane();
pane.add(panel);
theGUI.pack();
// Must be called after pack() so that size of panel is known
panel.startRendering();
theGUI.setVisible(true);
}
}
class ColorPanel extends JPanel {
private static final long serialVersionUID = 1L;
private boolean followMouse = true;
private int x, y;
private int seedx, seedy;
private int pointx, pointy;
private int dotcounter = 1;
private int newx, newy;
private Random random = new Random();
private javax.swing.Timer timer;
private EndPoint[] EP = new EndPoint[8];
private Seed seed;
private Color yellow = new Color(255, 255, 1);
private Color yellowOrange = new Color(255, 195, 0);
private Color orangeRed = new Color(255, 83, 0);
private Color violetRed = new Color(215, 0, 46);
private Color violet = new Color(129, 0, 127);
private Color violetBlue = new Color(44, 48, 156);
private Color blueGreen = new Color(0, 101, 87);
private Color yellowGreen = new Color(85, 171, 0);
private BufferedImage fractalImage;
public ColorPanel(Color backcolor) {
setBackground(backcolor);
setDoubleBuffered(true);
// constructor
addMouseListener(new SeedMouseListener());
addMouseMotionListener(new SeedMouseMotionListener());
this.setFocusable(true);
seed = new Seed(350, 350, Color.BLACK);
EP[0] = new EndPoint(350, 50, yellow);
EP[1] = new EndPoint(562, 138, yellowOrange);
EP[2] = new EndPoint(650, 350, orangeRed);
EP[3] = new EndPoint(562, 562, violetRed);
EP[4] = new EndPoint(350, 650, violet);
EP[5] = new EndPoint(138, 562, violetBlue);
EP[6] = new EndPoint(50, 350, blueGreen);
EP[7] = new EndPoint(138, 138, yellowGreen);
}
public void startRendering() {
// Create a buffered image to hold the fractal. Make the background
// transparent
fractalImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = fContext
StackExchange Code Review Q#82408, answer score: 6
Revisions (0)
No revisions yet.