动画演示 : 动画 « 图形用户界面 « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » 图形用户界面 » 动画屏幕截图 
动画演示
动画演示
  
/* From http://java.sun.com/docs/books/tutorial/index.html */

/*
 * @(#)Animator.java  1.5 95/11/29 Herb Jellinek
 *
 * Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
 * without fee is hereby granted.
 * Please refer to the file http://java.sun.com/copy_trademarks.html
 * for further important copyright and trademark information and to
 * http://java.sun.com/licensing.html for further important licensing
 * information for the Java (tm) Technology.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  SUN
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 */

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.image.ImageProducer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * An applet that plays a sequence of images, as a loop or a one-shot. Can have
 * a soundtrack and/or sound effects tied to individual frames.
 
 @author Herb Jellinek
 @version 1.5, 29 Nov 1995
 */

public class Animator extends Applet implements Runnable {

  /**
   * The images, in display order (Images).
   */
  Vector images = null;

  /**
   * Duration of each image (Integers, in milliseconds).
   */
  Hashtable durations = null;

  /**
   * Sound effects for each image (AudioClips).
   */
  Hashtable sounds = null;

  /**
   * Position of each image (Points).
   */
  Hashtable positions = null;

  /**
   * MediaTracker 'class' ID numbers.
   */

  static final int STARTUP_ID = 0;

  static final int BACKGROUND_ID = 1;

  static final int ANIMATION_ID = 2;

  /**
   * Start-up image URL, if any.
   */
  URL startUpImageURL = null;

  /**
   * Start-up image, if any.
   */
  Image startUpImage = null;

  /**
   * Background image URL, if any.
   */
  URL backgroundImageURL = null;

  /**
   * Background image, if any.
   */
  Image backgroundImage = null;

  /**
   * The soundtrack's URL.
   */
  URL soundtrackURL = null;

  /**
   * The soundtrack.
   */
  AudioClip soundtrack;

  /**
   * Largest width.
   */
  int maxWidth = 0;

  /**
   * Largest height.
   */
  int maxHeight = 0;

  /**
   * Was there a problem loading the current image?
   */
  boolean imageLoadError = false;

  /**
   * The directory or URL from which the images are loaded
   */
  URL imageSource = null;

  /**
   * The directory or URL from which the sounds are loaded
   */
  URL soundSource = null;

  /**
   * The thread animating the images.
   */
  Thread engine = null;

  /**
   * The current loop slot - index into 'images.'
   */
  int frameNum;

  /**
   * frameNum as an Object - suitable for use as a Hashtable key.
   */
  Integer frameNumKey;

  /**
   * The current X position (for painting).
   */
  int xPos = 0;

  /**
   * The current Y position (for painting).
   */
  int yPos = 0;

  /**
   * The default number of milliseconds to wait between frames.
   */
  public static final int defaultPause = 3900;

  /**
   * The global delay between images, which can be overridden by the PAUSE
   * parameter.
   */
  int globalPause = defaultPause;

  /**
   * Whether or not the thread has been paused by the user.
   */
  boolean userPause = false;

  /**
   * Repeat the animation? If false, just play it once.
   */
  boolean repeat;

  /**
   * The offscreen image, used in double buffering
   */
  Image offScrImage;

  /**
   * The offscreen graphics context, used in double buffering
   */
  Graphics offScrGC;

  /**
   * The MediaTracker we use to load our images.
   */
  MediaTracker tracker;

  /**
   * Can we paint yet?
   */
  boolean loaded = false;

  /**
   * Was there an initialization error?
   */
  boolean error = false;

  /**
   * What we call an image file in messages.
   */
  final static String imageLabel = "image";

  /**
   * What we call a sound file in messages.
   */
  final static String soundLabel = "sound";

  /**
   * Print silly debugging info?
   */
  final boolean debug = false;

  /**
   * Applet info.
   */
  public String getAppletInfo() {
    return "Animator v1.5, by Herb Jellinek";
  }

  /**
   * Parameter info.
   */
  public String[][] getParameterInfo() {
    String[][] info = { { "imagesource""URL""a directory" },
        "startup""URL""displayed at startup" },
        "background""URL""displayed as background" },
        "startimage""int""start index" },
        "endimage""int""end index" },
        "namepattern""URL""used to generate indexed names" },
        "pause""int""milliseconds" },
        "pauses""ints""milliseconds" },
        "repeat""boolean""repeat or not" },
        "positions""coordinates""path" },
        "soundsource""URL""audio directory" },
        "soundtrack""URL""background music" },
        "sounds""URLs""audio samples" }};
    return info;
  }

  /**
   * Print silly debugging info.
   */
  void dbg(String s) {
    if (debug) {
      System.out.println("> " + s);
    }
  }

  /**
   * Local version of getParameter for debugging purposes.
   */
  public String getParameter(String key) {
    String result = super.getParameter(key);
    dbg("getParameter(" + key + ") = " + result);
    return result;
  }

  final int setFrameNum(int newFrameNum) {
    frameNumKey = new Integer(frameNum = newFrameNum);
    return frameNum;
  }

  void updateMaxDims(Dimension dim) {
    maxWidth = Math.max(dim.width, maxWidth);
    maxHeight = Math.max(dim.height, maxHeight);
    dbg("New width = " + maxWidth + ", height = " + maxHeight);
  }

  /**
   * Parse the IMAGES parameter. It looks like 1|2|3|4|5, etc., where each
   * number (item) names a source image.
   
   @return a Vector of (URL) image file names.
   */
  Vector parseImages(String attrthrows MalformedURLException {
    Vector result = new Vector(10);
    for (int i = 0; i < attr.length();) {
      int next = attr.indexOf('|', i);
      if (next == -1)
        next = attr.length();
      String file = attr.substring(i, next);
      result.addElement(new URL(imageSource, "T" + file + ".gif"));
      i = next + 1;
    }
    return result;
  }

  /**
   * Fetch the images named in the argument, updating maxWidth and maxHeight
   * as we go. Is restartable.
   
   @param images
   *            a Vector of URLs
   @return true if all went well, false otherwise.
   */
  boolean fetchImages(Vector images) {
    int i;
    int size = images.size();
    for (i = 0; i < size; i++) {
      Object o = images.elementAt(i);
      if (instanceof URL) {
        URL url = (URLo;
        tellLoadingMsg(url, imageLabel);
        Image im = getImage(url);
        tracker.addImage(im, ANIMATION_ID);
        images.setElementAt(im, i);
      }
    }

    try {
      tracker.waitForID(ANIMATION_ID);
    catch (InterruptedException e) {
    }
    if (tracker.isErrorID(ANIMATION_ID)) {
      return false;
    }

    for (i = 0; i < size; i++) {
      updateMaxDims(getImageDimensions((Imageimages.elementAt(i)));
    }

    return true;
  }

  /**
   * Parse the SOUNDS parameter. It looks like train.au||hello.au||stop.au,
   * etc., where each item refers to a source image. Empty items mean that the
   * corresponding image has no associated sound.
   
   @return a Hashtable of SoundClips keyed to Integer frame numbers.
   */
  Hashtable parseSounds(String attr, Vector images)
      throws MalformedURLException {
    Hashtable result = new Hashtable();

    int imageNum = 0;
    int numImages = images.size();
    for (int i = 0; i < attr.length();) {
      if (imageNum >= numImages)
        break;

      int next = attr.indexOf('|', i);
      if (next == -1)
        next = attr.length();

      String sound = attr.substring(i, next);
      if (sound.length() != 0) {
        result.put(new Integer(imageNum)new URL(soundSource, sound));
      }
      i = next + 1;
      imageNum++;
    }

    return result;
  }

  /**
   * Fetch the sounds named in the argument. Is restartable.
   
   @return URL of the first bogus file we hit, null if OK.
   */
  URL fetchSounds(Hashtable sounds) {
    for (Enumeration e = sounds.keys(); e.hasMoreElements();) {
      Integer num = (Integere.nextElement();
      Object o = sounds.get(num);
      if (instanceof URL) {
        URL file = (URLo;
        tellLoadingMsg(file, soundLabel);
        try {
          sounds.put(num, getAudioClip(file));
        catch (Exception ex) {
          return file;
        }
      }
    }
    return null;
  }

  /**
   * Parse the PAUSES parameter. It looks like 1000|500|||750, etc., where
   * each item corresponds to a source image. Empty items mean that the
   * corresponding image has no special duration, and should use the global
   * one.
   
   @return a Hashtable of Integer pauses keyed to Integer frame numbers.
   */
  Hashtable parseDurations(String attr, Vector images) {
    Hashtable result = new Hashtable();

    int imageNum = 0;
    int numImages = images.size();
    for (int i = 0; i < attr.length();) {
      if (imageNum >= numImages)
        break;

      int next = attr.indexOf('|', i);
      if (next == -1)
        next = attr.length();

      if (i != next - 1) {
        int duration = Integer.parseInt(attr.substring(i, next));
        result.put(new Integer(imageNum)new Integer(duration));
      else {
        result.put(new Integer(imageNum)new Integer(globalPause));
      }
      i = next + 1;
      imageNum++;
    }

    return result;
  }

  /**
   * Parse a String of form xxx@yyy and return a Point.
   */
  Point parsePoint(String sthrows ParseException {
    int atPos = s.indexOf('@');
    if (atPos == -1)
      throw new ParseException("Illegal position: " + s);
    return new Point(Integer.parseInt(s.substring(0, atPos)), Integer
        .parseInt(s.substring(atPos + 1)));
  }

  /**
   * Parse the POSITIONS parameter. It looks like 10@30|11@31|||12@20, etc.,
   * where each item is an X@Y coordinate corresponding to a source image.
   * Empty items mean that the corresponding image has the same position as
   * the preceding one.
   
   @return a Hashtable of Points keyed to Integer frame numbers.
   */
  Hashtable parsePositions(String param, Vector imagesthrows ParseException {
    Hashtable result = new Hashtable();

    int imageNum = 0;
    int numImages = images.size();
    for (int i = 0; i < param.length();) {
      if (imageNum >= numImages)
        break;

      int next = param.indexOf('|', i);
      if (next == -1)
        next = param.length();

      if (i != next) {
        result.put(new Integer(imageNum), parsePoint(param.substring(i,
            next)));
      }
      i = next + 1;
      imageNum++;
    }

    return result;
  }

  /**
   * Get the dimensions of an image.
   
   @return the image's dimensions.
   */
  Dimension getImageDimensions(Image im) {
    return new Dimension(im.getWidth(null), im.getHeight(null));
  }

  /**
   * Substitute an integer some number of times in a string, subject to
   * parameter strings embedded in the string. Parameter strings: %N -
   * substitute the integer as is, with no padding. % <digit>, for example %5 -
   * substitute the integer left-padded with zeros to <digits>digits wide. %% -
   * substitute a '%' here.
   
   @param inStr
   *            the String to substitute within
   @param theInt
   *            the int to substitute.
   */
  String doSubst(String inStr, int theInt) {
    String padStr = "0000000000";
    int length = inStr.length();
    StringBuffer result = new StringBuffer(length);

    for (int i = 0; i < length;) {
      char ch = inStr.charAt(i);
      if (ch == '%') {
        i++;
        if (i == length) {
          result.append(ch);
        else {
          ch = inStr.charAt(i);
          if (ch == 'N') {
            // just stick in the number, unmolested
            result.append(theInt + "");
            i++;
          else {
            int pad;
            if ((pad = Character.digit(ch, 10)) != -1) {
              // we've got a width value
              String numStr = theInt + "";
              String scr = padStr + numStr;
              result.append(scr.substring(scr.length() - pad));
              i++;
            else {
              result.append(ch);
              i++;
            }
          }
        }
      else {
        result.append(ch);
        i++;
      }
    }
    return result.toString();
  }

  /**
   * Stuff a range of image names into a Vector.
   
   @return a Vector of image URLs.
   */
  Vector prepareImageRange(int startImage, int endImage, String pattern)
      throws MalformedURLException {
    Vector result = new Vector(Math.abs(endImage - startImage1);
    if (pattern == null) {
      pattern = "T%N.gif";
    }
    if (startImage > endImage) {
      for (int i = startImage; i >= endImage; i--) {
        result.addElement(new URL(imageSource, doSubst(pattern, i)));
      }
    else {
      for (int i = startImage; i <= endImage; i++) {
        result.addElement(new URL(imageSource, doSubst(pattern, i)));
      }
    }
    return result;
  }

  /**
   * Initialize the applet. Get parameters.
   */
  public void init() {

    tracker = new MediaTracker(this);

    try {
      String param = getParameter("IMAGESOURCE");
      imageSource = (param == null? getDocumentBase() new URL(
          getDocumentBase(), param + "/");

      param = getParameter("PAUSE");
      globalPause = (param != null? Integer.parseInt(param)
          : defaultPause;

      param = getParameter("REPEAT");
      repeat = (param == nulltrue
          (param.equalsIgnoreCase("yes"|| param
              .equalsIgnoreCase("true"));

      int startImage = 1;
      int endImage = 1;
      param = getParameter("ENDIMAGE");
      if (param != null) {
        endImage = Integer.parseInt(param);
        param = getParameter("STARTIMAGE");
        if (param != null) {
          startImage = Integer.parseInt(param);
        }
        param = getParameter("NAMEPATTERN");
        images = prepareImageRange(startImage, endImage, param);
      else {
        param = getParameter("STARTIMAGE");
        if (param != null) {
          startImage = Integer.parseInt(param);
          param = getParameter("NAMEPATTERN");
          images = prepareImageRange(startImage, endImage, param);
        else {
          param = getParameter("IMAGES");
          if (param == null) {
            showStatus("No legal IMAGES, STARTIMAGE, or ENDIMAGE "
                "specified.");
            return;
          else {
            images = parseImages(param);
          }
        }
      }

      param = getParameter("BACKGROUND");
      if (param != null) {
        backgroundImageURL = new URL(imageSource, param);
      }

      param = getParameter("STARTUP");
      if (param != null) {
        startUpImageURL = new URL(imageSource, param);
      }

      param = getParameter("SOUNDSOURCE");
      soundSource = (param == null? imageSource : new URL(
          getDocumentBase(), param + "/");

      param = getParameter("SOUNDS");
      if (param != null) {
        sounds = parseSounds(param, images);
      }

      param = getParameter("PAUSES");
      if (param != null) {
        durations = parseDurations(param, images);
      }

      param = getParameter("POSITIONS");
      if (param != null) {
        positions = parsePositions(param, images);
      }

      param = getParameter("SOUNDTRACK");
      if (param != null) {
        soundtrackURL = new URL(soundSource, param);
      }
    catch (MalformedURLException e) {
      showParseError(e);
    catch (ParseException e) {
      showParseError(e);
    }

    setFrameNum(0);
  }

  void tellLoadingMsg(String file, String fileType) {
    showStatus("Animator: loading " + fileType + " " + file);
  }

  void tellLoadingMsg(URL url, String fileType) {
    tellLoadingMsg(url.toExternalForm(), fileType);
  }

  void clearLoadingMessage() {
    showStatus("");
  }

  void loadError(String fileName, String fileType) {
    String errorMsg = "Animator: Couldn't load " + fileType + " "
        + fileName;
    showStatus(errorMsg);
    System.err.println(errorMsg);
    error = true;
    repaint();
  }

  void loadError(URL badURL, String fileType) {
    loadError(badURL.toExternalForm(), fileType);
  }

  void showParseError(Exception e) {
    String errorMsg = "Animator: Parse error: " + e;
    showStatus(errorMsg);
    System.err.println(errorMsg);
    error = true;
    repaint();
  }

  void startPlaying() {
    if (soundtrack != null) {
      soundtrack.loop();
    }
  }

  void stopPlaying() {
    if (soundtrack != null) {
      soundtrack.stop();
    }
  }

  /**
   * Run the animation. This method is called by class Thread.
   
   @see java.lang.Thread
   */
  public void run() {
    Thread me = Thread.currentThread();
    URL badURL;

    me.setPriority(Thread.MIN_PRIORITY);

    if (!loaded) {
      try {
        // ... to do a bunch of loading.
        if (startUpImageURL != null) {
          tellLoadingMsg(startUpImageURL, imageLabel);
          startUpImage = getImage(startUpImageURL);
          tracker.addImage(startUpImage, STARTUP_ID);
          tracker.waitForID(STARTUP_ID);
          if (tracker.isErrorID(STARTUP_ID)) {
            loadError(startUpImageURL, "start-up image");
          }
          Dimension size = getImageDimensions(startUpImage);
          resize(size.width, size.height);
          repaint();
        }

        if (backgroundImageURL != null) {
          tellLoadingMsg(backgroundImageURL, imageLabel);
          backgroundImage = getImage(backgroundImageURL);
          tracker.addImage(backgroundImage, BACKGROUND_ID);
          tracker.waitForID(BACKGROUND_ID);
          if (tracker.isErrorID(BACKGROUND_ID)) {
            loadError(backgroundImageURL, "background image");
          }
          updateMaxDims(getImageDimensions(backgroundImage));
          repaint();
        }

        // Fetch the animation frames
        if (!fetchImages(images)) {
          // Need to add method to MediaTracker to return
          // files that caused errors during loading.
          loadError("an image", imageLabel);
          return;
        }

        if (soundtrackURL != null && soundtrack == null) {
          tellLoadingMsg(soundtrackURL, imageLabel);
          soundtrack = getAudioClip(soundtrackURL);
          if (soundtrack == null) {
            loadError(soundtrackURL, "soundtrack");
            return;
          }
        }

        if (sounds != null) {
          badURL = fetchSounds(sounds);
          if (badURL != null) {
            loadError(badURL, soundLabel);
            return;
          }
        }

        clearLoadingMessage();

        offScrImage = createImage(maxWidth, maxHeight);
        offScrGC = offScrImage.getGraphics();
        offScrGC.setColor(Color.white);

        resize(maxWidth, maxHeight);
        loaded = true;
        error = false;
      catch (Exception e) {
        error = true;
        e.printStackTrace();
      }
    }

    if (userPause) {
      return;
    }

    if (repeat || frameNum < images.size()) {
      startPlaying();
    }

    try {
      if (images.size() 1) {
        while (maxWidth > && maxHeight > && engine == me) {
          if (frameNum >= images.size()) {
            if (!repeat) {
              return;
            }
            setFrameNum(0);
          }
          repaint();

          if (sounds != null) {
            AudioClip clip = (AudioClipsounds.get(frameNumKey);
            if (clip != null) {
              clip.play();
            }
          }

          try {
            Integer pause = null;
            if (durations != null) {
              pause = (Integerdurations.get(frameNumKey);
            }
            if (pause == null) {
              Thread.sleep(globalPause);
            else {
              Thread.sleep(pause.intValue());
            }
          catch (InterruptedException e) {
            // Should we do anything?
          }
          setFrameNum(frameNum + 1);
        }
      }
    finally {
      stopPlaying();
    }
  }

  /**
   * No need to clear anything; just paint.
   */
  public void update(Graphics g) {
    paint(g);
  }

  /**
   * Paint the current frame.
   */
  public void paint(Graphics g) {
    if (error || !loaded) {
      if (startUpImage != null) {
        if (tracker.checkID(STARTUP_ID)) {
          g.drawImage(startUpImage, 00this);
        }
      else {
        if (backgroundImage != null) {
          if (tracker.checkID(BACKGROUND_ID)) {
            g.drawImage(backgroundImage, 00this);
          }
        else {
          g.clearRect(00, maxWidth, maxHeight);
        }
      }
    else {
      if ((images != null&& (images.size() 0)) {
        if (frameNum < images.size()) {
          if (backgroundImage == null) {
            offScrGC.fillRect(00, maxWidth, maxHeight);
          else {
            offScrGC.drawImage(backgroundImage, 00this);
          }

          Image image = (Imageimages.elementAt(frameNum);
          Point pos = null;
          if (positions != null) {
            pos = (Pointpositions.get(frameNumKey);
          }
          if (pos != null) {
            xPos = pos.x;
            yPos = pos.y;
          }
          offScrGC.drawImage(image, xPos, yPos, this);
          g.drawImage(offScrImage, 00this);
        else {
          // no more animation, but need to draw something
          dbg("No more animation; drawing last image.");
          if (backgroundImage == null) {
            g.fillRect(00, maxWidth, maxHeight);
          else {
            g.drawImage(backgroundImage, 00this);
          }
          g.drawImage((Imageimages.lastElement()00this);
        }
      }
    }
  }

  /**
   * Start the applet by forking an animation thread.
   */
  public void start() {
    if (engine == null) {
      engine = new Thread(this);
      engine.start();
    }
  }

  /**
   * Stop the insanity, um, applet.
   */
  public void stop() {
    if (engine != null && engine.isAlive()) {
      engine.stop();
    }
    engine = null;
  }

  /**
   * Pause the thread when the user clicks the mouse in the applet. If the
   * thread has stopped (as in a non-repeat performance), restart it.
   */
  public boolean handleEvent(Event evt) {
    if (evt.id == Event.MOUSE_DOWN) {
      if (loaded) {
        if (engine != null && engine.isAlive()) {
          if (userPause) {
            engine.resume();
            startPlaying();
          else {
            engine.suspend();
            stopPlaying();
          }
          userPause = !userPause;
        else {
          userPause = false;
          setFrameNum(0);
          engine = new Thread(this);
          engine.start();
        }
      }
      return true;
    else {
      return super.handleEvent(evt);
    }
  }

}

class ParseException extends Exception {
  ParseException(String s) {
    super(s);
  }
}

class ImageNotFoundException extends Exception {
  ImageNotFoundException(ImageProducer source) {
    super(source + "");
  }
}

           
         
    
  
Related examples in the same category
1. 事件调度线程事件调度线程
2. 定时器的动画
3. 旋转和缩放矩形。
4. 淡出图像:形象逐步得到更加透明,直到它完全是无形的。
5. 字体大小动画
6. 催眠动画催眠动画
7. 噪声图像噪声图像
8. 如何创建动画:绘制和线程如何创建动画:绘制和线程
9. 如何创建动画如何创建动画
10. 跳出线程跳出线程
11. 动画:反弹
12. 图像反弹图像反弹
13. 文字动画文字动画
14. 缓冲动画演示缓冲动画演示
15. 弹跳圈弹跳圈
16. 催眠螺旋催眠螺旋
17. 河内塔
18. 制作自己的动画:一系列的图像
19. 动画组成技术
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.