Hypnosispublic class Hypnosis extends JComponent implements ActionListenerA Swing component that smoothly animates a spiral in a hypnotic way. |
Fields Summary |
---|
double | x | double | y | double | r1 | double | r2 | double | a1 | double | a2 | double | deltaA | double | deltaX | double | deltaY | float | linewidth | Timer | timer | BufferedImage | buffer | Graphics2D | osg |
Constructors Summary |
---|
public Hypnosis(double x, double y, double r1, double r2, double a1, double a2, float linewidth, int delay, double deltaA, double deltaX, double deltaY)
this.x = x; this.y = y;
this.r1 = r1; this.r2 = r2;
this.a1 = a1; this.a2 = a2;
this.linewidth = linewidth;
this.deltaA = deltaA;
this.deltaX = deltaX;
this.deltaY = deltaY;
// Set up a timer to call actionPerformed() every delay milliseconds
timer = new Timer(delay, this);
// Create a buffer for double-buffering
buffer = new BufferedImage((int)(2*r2+linewidth),
(int)(2*r2+linewidth),
BufferedImage.TYPE_INT_RGB);
// Create a Graphics object for the buffer, and set the linewidth
// and request antialiasing when drawing with it
osg = buffer.createGraphics();
osg.setStroke(new BasicStroke(linewidth, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
osg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
|
Methods Summary |
---|
public void | actionPerformed(java.awt.event.ActionEvent e)This method implements the ActionListener interface. Our Timer object
calls this method periodically. It updates the position and angles
of the spiral and requests a redraw. Instead of redrawing the entire
component, however, this method requests a redraw only for the
area that has changed.
// Ask to have the old bounding box of the spiral redrawn.
// Nothing else has anything drawn in it, so it doesn't need a redraw
repaint((int)(x-r2-linewidth), (int)(y-r2-linewidth),
(int)(2*(r2+linewidth)), (int)(2*(r2+linewidth)));
// Now animate: update the position and angles of the spiral
// Bounce if we've hit an edge
Rectangle bounds = getBounds();
if ((x - r2 + deltaX < 0) || (x + r2 + deltaX > bounds.width))
deltaX = -deltaX;
if ((y - r2 + deltaY < 0) || (y + r2 + deltaY > bounds.height))
deltaY = -deltaY;
// Move the center of the spiral
x += deltaX;
y += deltaY;
// Increment the start and end angles;
a1 += deltaA;
a2 += deltaA;
if (a1 > 2*Math.PI) { // Don't let them get too big
a1 -= 2*Math.PI;
a2 -= 2*Math.PI;
}
// Now ask to have the new bounding box of the spiral redrawn. This
// rectangle will be intersected with the redraw rectangle requested
// above, and only the combined region will be redrawn
repaint((int)(x-r2-linewidth), (int)(y-r2-linewidth),
(int)(2*(r2+linewidth)), (int)(2*(r2+linewidth)));
| public boolean | isDoubleBuffered()Tell Swing not to double-buffer for us, since we do our own return false;
| public static void | main(java.lang.String[] args)This is a main() method for testing the component
JFrame f = new JFrame("Hypnosis");
Hypnosis h = new Hypnosis(200, 200, 10, 100, 0, 5*Math.PI, 10, 100,
2*Math.PI/15, 3, 5);
f.getContentPane().add(h, BorderLayout.CENTER);
f.setSize(400, 400);
f.show();
h.start();
| public void | paintComponent(java.awt.Graphics g)Swing calls this method to ask the component to redraw itself.
This method uses double-buffering to make the animation smoother.
Swing does double-buffering automatically, so this may not actually
make much difference, but it is important to understand the technique.
// Clear the background of the off-screen image
osg.setColor(getBackground());
osg.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
// Now draw a black spiral into the off-screen image
osg.setColor(Color.black);
osg.draw(new Spiral(r2+linewidth/2, r2+linewidth/2, r1, a1, r2, a2));
// Now copy that off-screen image onto the screen
g.drawImage(buffer, (int)(x-r2), (int)(y-r2), this);
| public void | start() timer.start();
| public void | stop() timer.stop();
|
|