Swing Components Java

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import org.jdesktop.animation.timing.Animator;
import org.jdesktop.animation.timing.Animator.RepeatBehavior;
import org.jdesktop.animation.timing.interpolation.Interpolator;
import org.jdesktop.animation.timing.interpolation.KeyFrames;
import org.jdesktop.animation.timing.interpolation.KeyTimes;
import org.jdesktop.animation.timing.interpolation.KeyValues;
import org.jdesktop.animation.timing.interpolation.PropertySetter;
import org.jdesktop.animation.timing.interpolation.SplineInterpolator;
import org.jdesktop.animation.timing.triggers.ActionTrigger;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.Point;
import javax.swing.JComponent;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.applet.AudioClip;
import java.net.URL;
import org.jdesktop.animation.timing.TimingTarget;
import org.jdesktop.animation.timing.interpolation.KeyFrames;
/*
 * MultiStepRace.java
 *
 * Created on May 3, 2007, 2:45 PM
 *
 * Copyright (c) 2007, Sun Microsystems, Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TimingFramework project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.UIManager;
 
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
 * The full-blown demo with all of the bells and whistles.  This one uses
 * the facilities shown in all of the other variations, but adds 
 * both multi-step and non-linear interpolation.  It does this by
 * creating a KeyFrames object to hold the times/values/splines
 * used for each segment of the race.  It also adds an animation for
 * the rotation of the car (since the car should turn as it goes around the
 * curves) and sound effects (just to go completely overboard).
 *
 * @author Chet
 */
public class MultiStepRace {
    
    protected Animator animator;
    private SoundEffects soundEffects;
    public static final int RACE_TIME = 10000;
    
    
    /** Creates a new instance of BasicRace */
    public MultiStepRace(String appName) {
        RaceGUI basicGUI = new RaceGUI(appName);
        
        // We're going to need a more involved PropertyRange object
        // that has all curves of the track in it, as well as 
        // non-linear movement around the curves
        Point values[] = {
            TrackView.START_POS,
            TrackView.FIRST_TURN_START, TrackView.FIRST_TURN_END,
            TrackView.SECOND_TURN_START, TrackView.SECOND_TURN_END,
            TrackView.THIRD_TURN_START, TrackView.THIRD_TURN_END,
            TrackView.FOURTH_TURN_START, 
            TrackView.START_POS};
        KeyValues keyValues = KeyValues.create(values);
        // Calculate the keyTimes based on the distances that must be
        // traveled on each leg of the journey
        double totalDistance = 0;
        double segmentDistance[] = new double[values.length];
        for (int i = 0; i < (values.length - 1); ++i) {
            segmentDistance[i] = values[i].distance(values[i + 1]);
            totalDistance += segmentDistance[i];
        }
        segmentDistance[(values.length-1)] = 
                values[(values.length - 1)].distance(values[0]);
        totalDistance += segmentDistance[(values.length-1)];
        float times[] = new float[values.length];
        float elapsedTime = 0.0f;
        times[0] = 0.0f;
        times[values.length - 1] = 1.0f;
        for (int i = 0; i < (values.length - 2); ++i) {
            times[i + 1] = elapsedTime + (float)(segmentDistance[i] / totalDistance);
            elapsedTime = times[i + 1];
        }
        KeyTimes keyTimes = new KeyTimes(times);
        // For realistic movement, we want a big acceleration
        // on the straightaways
        Interpolator initialSpline = new SplineInterpolator(1.00f, 0.00f, 0.2f, .2f);
        Interpolator straightawaySpline = new SplineInterpolator(0.50f, 0.20f, .50f, .80f);
        Interpolator curveSpline = new SplineInterpolator(0.50f, 0.20f, .50f, .80f);
        Interpolator finalSpline = new SplineInterpolator(0.50f, 0.00f, .50f, 1.00f);
        KeyFrames keyFrames = new KeyFrames(keyValues, keyTimes,
                initialSpline, curveSpline, straightawaySpline, curveSpline,
                straightawaySpline, curveSpline,
                straightawaySpline, finalSpline);
        // This PropertySetter enables the animation for the car movement all 
        // the way around the track
        PropertySetter modifier = new PropertySetter(basicGUI.getTrack(), 
                "carPosition", keyFrames);
        animator = new Animator(RACE_TIME, Animator.INFINITE,
                RepeatBehavior.LOOP, modifier);
        
        // Now create similar keyframes for rotation of car
        keyValues = KeyValues.create(360, 315, 270, 225, 180, 135, 90, 45, 0);
        Interpolator straightawayTurnSpline = new SplineInterpolator(1.0f, 0.0f, 1.0f, 0.0f);
        Interpolator curveTurnSpline = new SplineInterpolator(0.0f, 0.5f, 0.5f, 1.0f);
        keyFrames = new KeyFrames(keyValues, keyTimes, 
                straightawayTurnSpline, curveTurnSpline, 
                straightawayTurnSpline, curveTurnSpline, 
                straightawayTurnSpline, curveTurnSpline, 
                straightawayTurnSpline, curveTurnSpline);
        modifier = new PropertySetter(basicGUI.getTrack(), "carRotation", 
                keyFrames);
        animator.addTarget(modifier);
        
        // Finally, add sound effects, triggered by the same animator
        soundEffects = new SoundEffects(keyFrames);
        animator.addTarget(soundEffects);
        
        // Instead of manually tracking the events, have the framework do
        // the work by setting up a trigger
        JButton goButton = basicGUI.getControlPanel().getGoButton();
        JButton stopButton = basicGUI.getControlPanel().getStopButton();
        ActionTrigger trigger = ActionTrigger.addTrigger(goButton, animator);
        stopButton.addActionListener(new Stopper(animator));
    }
    /**
     * Handle clicks on the Stop button to stop the race
     */
    private class Stopper implements ActionListener {
        Animator timer;
        Stopper(Animator timer) {
            this.timer = timer;
        }
        public void actionPerformed(ActionEvent ae) {
            timer.stop();
        }
    }
    public static void main(String args[]) {
        Runnable doCreateAndShowGUI = new Runnable() {
            public void run() {
                MultiStepRace race = new MultiStepRace("Multi Step Race");
            }
        };
        SwingUtilities.invokeLater(doCreateAndShowGUI);
    }
    
}
/**
 * Copyright (c) 2007, Sun Microsystems, Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TimingFramework project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * Go/Stop buttons to control the animation
 *
 * @author Chet
 */
class RaceControlPanel extends JPanel {
    
    /** Make these static so that outside classes can easily
     *  add themselves as listeners */
    JButton goButton = new JButton("Go");
    JButton stopButton = new JButton("Stop");
    /**
     * Creates a new instance of RaceControlPanel
     */
    public RaceControlPanel() {
        add(goButton);
        add(stopButton);
    }
    
    public JButton getGoButton() {
        return goButton;
    }
    
    public JButton getStopButton() {
        return stopButton;
    }
    
    public void addListener(ActionListener listener) {
        goButton.addActionListener(listener);
        stopButton.addActionListener(listener);
    }
    
}
/**
 * Copyright (c) 2007, Sun Microsystems, Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TimingFramework project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * The GUI used by all of the different race demos.
 * It contains a control panel (for the Go/Stop buttons) and a
 * TrackView (where the race is rendered)
 *
 * @author Chet
 */
class RaceGUI {
    private TrackView track;
    private RaceControlPanel controlPanel;
    /**
     * Creates a new instance of RaceGUI
     */
    public RaceGUI(String appName) {
        UIManager.put("swing.boldMetal", Boolean.FALSE);
        JFrame f = new JFrame(appName);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new BorderLayout());
        
        // Add Track view
        track = new TrackView();
        f.add(track, BorderLayout.CENTER);
        
        // Add control panel
        controlPanel = new RaceControlPanel();
        f.add(controlPanel, BorderLayout.SOUTH);
        
        f.pack();
        f.setVisible(true);
    }
    
    public TrackView getTrack() {
        return track;
    }
    
    public RaceControlPanel getControlPanel() {
        return controlPanel;
    }
}
/**
 * Copyright (c) 2007, Sun Microsystems, Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TimingFramework project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * Simple utility class used to load and play sound effects for
 * MultiStepRace.
 *
 * @author Chet
 */
class SoundEffects implements TimingTarget {
    
    AudioClip drivingClip;
    AudioClip turningClip;
    KeyFrames keyFrames;
    
    /** Creates a new instance of SoundEffects */
    public SoundEffects(KeyFrames keyFrames) {
        this.keyFrames = keyFrames;
        try {
            URL url  = SoundEffects.class.getResource("vroom.wav");
            drivingClip = java.applet.Applet.newAudioClip(url);
            url  = SoundEffects.class.getResource("drift.wav");
            turningClip = java.applet.Applet.newAudioClip(url);
        } catch (Exception e) {
            System.out.println("Problem loading track/car images: " + e);
        }
    }
    
    /**
     * Plays the driving clip
     */
    public void drive() {
        if (drivingClip != null) {
            drivingClip.loop();
        }
    }
    
    /**
     * Stops current clips
     */
    public void stop() {
        if (drivingClip != null) {
            drivingClip.stop();
        }
        if (turningClip != null) {
            turningClip.stop();
        }
    }
    
    /**
     * Plays the turning clip
     */
    public void turn() {
        if (turningClip != null) {
            turningClip.play();
        }
    }
    
    // TimingTarget implementation
    
    boolean pastFirstTurn = false;
    boolean pastSecondTurn = false;
    boolean pastThirdTurn = false;
    boolean pastFourthTurn = false;
    
    public void begin() {
        drive();
        pastFirstTurn = false;
        pastSecondTurn = false;
        pastThirdTurn = false;
        pastFourthTurn = false;
    }
    
    public void end() {
        stop();
    }
    
    /**
     * This method figures out when the car hits one of the turns
     * and plays the turn clip appropriately
     */
    public void timingEvent(float fraction) {
       if (!pastFirstTurn) {
           if (keyFrames.getInterval(fraction) == 1) {
               turn();
               pastFirstTurn = true;
           }
       } else if (!pastSecondTurn) {
           if (keyFrames.getInterval(fraction) == 3) {
               turn();
               pastSecondTurn = true;
           }
       } else if (!pastThirdTurn) {
           if (keyFrames.getInterval(fraction) == 5) {
               turn();
               pastThirdTurn = true;
           }
       } else if (!pastFourthTurn) {
           if (keyFrames.getInterval(fraction) == 7) {
               turn();
               pastFourthTurn = true;
           }
       }
    }
    public void repeat() {
        pastFirstTurn = false;
        pastSecondTurn = false;
        pastThirdTurn = false;
        pastFourthTurn = false;
    }    
}
/**
 * Copyright (c) 2007, Sun Microsystems, Inc
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the TimingFramework project nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * This class does the work of rendering the current view of the
 * racetrack.  It holds the car position and rotation and displays
 * the car accordingly.  The track itself is merely a background image
 * that is copied the same on every repaint.
 * Note that carPosition and carRotation are both JavaBean properties, which
 * is exploited in the SetterRace and MultiStepRace variations.
 *
 * @author Chet
 */
class TrackView extends JComponent {
    
    BufferedImage car;
    BufferedImage track;
    Point carPosition;
    double carRotation = 0;
    int trackW, trackH;
    int carW, carH, carWHalf, carHHalf;
    /** Hard-coded positions of interest on the track */
    static final Point START_POS = new Point(450, 70);
    static final Point FIRST_TURN_START = new Point(130, 70);
    static final Point FIRST_TURN_END = new Point(76, 127);
    static final Point SECOND_TURN_START = new Point(76, 404);
    static final Point SECOND_TURN_END = new Point(130, 461);
    static final Point THIRD_TURN_START = new Point(450, 461);
    static final Point THIRD_TURN_END = new Point(504, 404);
    static final Point FOURTH_TURN_START = new Point(504, 127);
    
    /** Creates a new instance of TrackView */
    public TrackView() {
        try {
            car = ImageIO.read(TrackView.class.getResource("beetle_red.gif"));
            track = ImageIO.read(TrackView.class.getResource("track.jpg"));
        } catch (Exception e) {
            System.out.println("Problem loading track/car images: " + e);
        }
        carPosition = new Point(START_POS.x, START_POS.y);
        carW = car.getWidth();
        carH = car.getHeight();
        carWHalf = carW / 2;
        carHHalf = carH / 2;
        trackW = track.getWidth();
        trackH = track.getHeight();
    }
    
    public Dimension getPreferredSize() {
        return new Dimension(trackW, trackH);
    }
    
    /**
     * Render the track and car
     */
    public void paintComponent(Graphics g) {
        // First draw the race track
        g.drawImage(track, 0, 0, null);
        
        // Now draw the car.  The translate/rotate/translate settings account
        // for any nonzero carRotation values
        Graphics2D g2d = (Graphics2D)g.create();
        g2d.translate(carPosition.x, carPosition.y);
        g2d.rotate(Math.toRadians(carRotation));
        g2d.translate(-(carPosition.x), -(carPosition.y));
        
        // Now the graphics has been set up appropriately; draw the
        // car in position
        g2d.drawImage(car, carPosition.x - carWHalf, carPosition.y - carHHalf, null);
    }
    
    /**
     * Set the new position and schedule a repaint
     */
    public void setCarPosition(Point newPosition) {
        repaint(0, carPosition.x - carWHalf, carPosition.y - carHHalf,
                carW, carH);
        carPosition.x = newPosition.x;
        carPosition.y = newPosition.y;
        repaint(0, carPosition.x - carWHalf, carPosition.y - carHHalf,
                carW, carH);
    }
    
    /**
     * Set the new rotation and schedule a repaint
     */
    public void setCarRotation(double newDegrees) {
        carRotation = newDegrees;
        // repaint area accounts for larger rectangular are because rotate
        // car will exceed normal rectangular bounds
        repaint(0, carPosition.x - carW, carPosition.y - carH,
                2 * carW, 2 * carH);
    }
        
}
           
       
Filthy-Rich-Clients-MultiStepRace.zip( 3,970 k)