I made a program to display interference patterns for light waves. I did this by using the paint method on a JPanel to draw 2 sources and then drawing concentric circles around them. This would be double slit interference, so I allowed one of the sources to move around to experiment with the slit width.
The problem is that when I run this, my computer says it is using 80% of my CPU! There's really not much to it. Circle in the middle, circles around it, and it moves. My code follows.
main class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class main {
static final int UP = -1;
static final int DOWN = 1;
static final int RIGHT = 1;
static final int LEFT = -1;
static final int NOMOVEMENT = 0;
static int verticalMovement = NOMOVEMENT;
static int horizontalMovement = NOMOVEMENT;
public static void main(String[] args) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Point s1 = new Point((int)(screenSize.getWidth()/3), 50);
Point s2 = new Point((int)(2*screenSize.getWidth()/3), 50);
JFrame frame = new JFrame("Physics Frame");
frame.setPreferredSize(screenSize);
PhysicsPane pane = new PhysicsPane(screenSize, 15, s1, s2);
pane.setPreferredSize(screenSize);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
Timer time = new Timer(1000 / 20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switch (verticalMovement){
case UP:
s2.changeY(UP);
break;
case DOWN:
s2.changeY(DOWN);
break;
default:
break;
}
switch (horizontalMovement){
case RIGHT:
s2.changeX(RIGHT);
break;
case LEFT:
s2.changeX(LEFT);
break;
default:
break;
}
pane.repaint();
}
});
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==37){
horizontalMovement = LEFT;
} else if (e.getKeyCode()==38){
verticalMovement = UP;
} else if (e.getKeyCode()==39){
horizontalMovement = RIGHT;
} else if (e.getKeyCode()==40){
verticalMovement = DOWN;
}
if(e.getKeyChar()=='a'){
pane.setWaveLength(2);
}
if(e.getKeyChar()=='s'){
pane.setWaveLength(-2);
}
}
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()){
case 37:
horizontalMovement = NOMOVEMENT;
break;
case 38:
verticalMovement = NOMOVEMENT;
break;
case 39:
horizontalMovement = NOMOVEMENT;
break;
case 40:
verticalMovement = NOMOVEMENT;
break;
}
}
});
frame.setVisible(true);
time.start();
}
}
Panel class. If there's an inefficiency with the drawing method, it would be here.
import javax.swing.*;
import java.awt.*;
public class PhysicsPane extends JPanel {
private Dimension size;
private Point[] pointArray = new Point[2];
private double waveLength;
public PhysicsPane(Dimension size, double wavelength, Point source1, Point source2) {
this.size = size;
pointArray[0] = source1;
pointArray[1] = source2;
setPreferredSize(size);
this.waveLength = wavelength;
}
@Override
public void paintComponent(Graphics g){
for (int i = 0; i < 2; i++) {
g.setColor(Color.black);
double x = this.pointArray[i].getX();
double y = this.pointArray[i].getY();
g.fillOval((int)x, (int)y, 2, 2);
for (int j = (int)waveLength; j < 1500; j+=waveLength) {
g.setColor(Color.red);
g.drawOval((int)x-(j/2+1), (int)y-(j/2+1), 2 + j, 2 + j);
}
}
}
public void setWaveLength(double increment){
this.waveLength+=increment;
}
}
Point Class: Really just puts x and y coordinates into one construct. Not important particularly
public class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public void changeX(double dX){
this.x+=dX;
}
public void changeY(double dY){
this.y+=dY;
}
}
So what is wrong with my program? Why is such a simple animation consuming so much of my processor?
UPDATED CODE SECTION:
@Override
public void paintComponent(Graphics g){
BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = bi.getGraphics();
for (int i = 0; i < 2; i++) {
graphics.setColor(Color.black);
double x = this.pointArray[i].getX();
double y = this.pointArray[i].getY();
graphics.fillOval((int)x, (int)y, 2, 2);
for (int j = (int)waveLength; j < 1500; j+=waveLength) {
graphics.setColor(Color.red);
graphics.drawOval((int)x-(j/2+1), (int)y-(j/2+1), 2 + j, 2 + j);
}
}
g.drawImage(bi, 0, 0, new ImageObserver() {
@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
return false;
}
});
}