/* * [TestAnimation.java] * * Summary: Demonstration of simple animation. * * Copyright: (c) 2011-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2011-10-30 initial version */ package com.mindprod.example; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.Timer; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * Demonstration of simple animation. *

* A square bounces diagonally up and down. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2011-10-30 initial version * @since 2011-10-30 */ public final class TestAnimation { /** * how big a square canvas to draw on. */ private static final int CANVAS_SIZE = 300; /** * interval between painting frames in millis. Note int not long. */ private static final int INTERVAL = 20; /** * where we draw the bouncing square */ private static Bouncer canvas; /** * Test harness * * @param args not used */ public static void main( String[] args ) { // fire up application on the Swing Thread SwingUtilities.invokeLater( new Runnable() { /** * do all swing work on the swing thread. */ public void run() { canvas = new Bouncer(); canvas.setBackground( new Color( 0xf3fff6 ) /* pale green */ ); canvas.setForeground( new Color( 0x6495ed ) /* cornflower blue */ ); JFrame.setDefaultLookAndFeelDecorated( true ); final JFrame frame = new JFrame( "Bouncing Square" ); frame.setResizable( false ); frame.setUndecorated( false ); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); // allow some extra room for the frame title bar. frame.setSize( CANVAS_SIZE + 24, CANVAS_SIZE + 64 ); frame.getContentPane().add( canvas ); frame.validate(); frame.setVisible( true ); // this is a javax.swing.Timer, not to be confused with java.util.Timer; final Timer animationTimer = new Timer( INTERVAL, new ActionListener() { /** * invoked whenever Timer triggers * @param e event not used. */ public void actionPerformed( ActionEvent e ) { canvas.repaint(); } } ); animationTimer.setRepeats( true ); animationTimer.start(); } // end run } // end Runnable ); } // end main } /** * Animated panel used to draw a bouncing square */ class Bouncer extends JPanel { /** * how big a border to leave around area we draw bouncing square on, keep out the way of the Frame bar */ private static final int BORDER = 50; /** * how big the bouncing square is on edge in pixels */ private static final int SQUARE_SIZE = 20; /** * true if square is moving up, toward smaller values of y */ private boolean ascending = false; /** * top edge of the square where the square should be now. */ private int newY = BORDER; Bouncer() { // we don't want Swing painting any flicker-causing backgrounds. // we want to be responsible for painting the background. setOpaque( true ); } /** * draws one frame of the animation. * * @param g where to paint. */ public void paintComponent( Graphics g ) { super.paintComponent( g ); // how high we should let top edge of square move to final int highestPoint = BORDER; /// how low we should let top edge of square move to final int lowestPoint = getHeight() - BORDER - SQUARE_SIZE; // reverse direction when runs off the end. final int oldY = newY; if ( ascending ) { newY--; // ascend one pixel if ( newY <= highestPoint ) { ascending = false; // reverse direction } } else { newY++; // descend one pixel if ( newY >= lowestPoint ) { ascending = true; // reverse direction } } // erase old square. Ideally we would clip to region that does not overlap new square. // Swing's double buffering should hide the flicker g.setColor( getBackground() ); g.fillRect( oldY, oldY, SQUARE_SIZE, SQUARE_SIZE ); // paint new square, one pixel offset. g.setColor( getForeground() ); g.fillRect( newY, newY, SQUARE_SIZE, SQUARE_SIZE ); } }