• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:Timerでアニメーションするアイコンを作成
#navi(../)
*Timerでアニメーションするアイコンを作成 [#k26d808e]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2006-03-13~
更新日:&lastmod;

#contents

**概要 [#k5877eb2]
javax.swing.Timerを使って、アニメーションするアイコンを作成します。

#screenshot

**サンプルコード [#z490c564]
#code{{
 class AnimeIcon extends JComponent implements ActionListener {
   private boolean flag = false;
   private final javax.swing.Timer animator;
   private final Vector list = new Vector();
   public void animationStart() {
     flag = true;
     animator.start();
   }
   public void animationStop() {
     flag = false;
     animator.stop();
   }
   public AnimeIcon() {
     super();
     animator = new javax.swing.Timer(100, this);
     double r  = 2.0d;
     double sx = 1.0d;
     double sy = 1.0d;
     list.addElement(new Ellipse2D.Double(sx+3*r, sy+0*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+5*r, sy+1*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+6*r, sy+3*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+5*r, sy+5*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+3*r, sy+6*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+1*r, sy+5*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+0*r, sy+3*r, 2*r, 2*r));
     list.addElement(new Ellipse2D.Double(sx+1*r, sy+1*r, 2*r, 2*r));
     int iw = (int)(r*8)+(int)(sx*2);
     int ih = (int)(r*8)+(int)(sy*2);
     setPreferredSize(new Dimension(iw, ih));
   }
   public void paintComponent(Graphics g) {
     Graphics2D g2d = (Graphics2D) g;
     g2d.setPaint(getBackground());
     g2d.fillRect(0, 0, getWidth(), getHeight());
     g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_ON);
     g2d.setPaint(cColor);
     float alpha = 0.0f;
     Iterator it = list.iterator();
     while(it.hasNext()) {
       alpha = (flag)?alpha+0.1f:0.5f;
       g2d.setComposite(AlphaComposite.getInstance(
         AlphaComposite.SRC_OVER, alpha));
       g2d.fill((Shape)it.next());
     }
   }
   public void actionPerformed(ActionEvent e) {
     list.addElement(list.remove(0));
     repaint();
   }
 }
class AnimatedLabel extends JLabel implements ActionListener {
  private final javax.swing.Timer animator;
  private final AnimeIcon icon = new AnimeIcon();
  public AnimatedLabel() {
    super();
    animator = new javax.swing.Timer(100, this);
    setIcon(icon);
  }
  public void actionPerformed(ActionEvent e) {
    icon.next();
    repaint();
  }
  public void startAnimation() {
    icon.setRunning(true);
    animator.start();
  }
  public void stopAnimation() {
    icon.setRunning(false);
    animator.stop();
  }
}

class AnimeIcon implements Icon {
  private static final Color cColor = new Color(0.5f,0.5f,0.5f);
  private final Vector list = new Vector();
  private final Dimension dim;
  private boolean isRunning = false;
  public AnimeIcon() {
    super();
    double r  = 2.0d;
    double sx = 1.0d;
    double sy = 1.0d;
    list.addElement(new Ellipse2D.Double(sx+3*r, sy+0*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+5*r, sy+1*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+6*r, sy+3*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+5*r, sy+5*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+3*r, sy+6*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+1*r, sy+5*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+0*r, sy+3*r, 2*r, 2*r));
    list.addElement(new Ellipse2D.Double(sx+1*r, sy+1*r, 2*r, 2*r));
    int iw = (int)(r*8)+(int)(sx*2);
    int ih = (int)(r*8)+(int)(sy*2);
    dim = new Dimension(iw, ih);
  }
  public int getIconWidth() {
    return dim.width;
  }
  public int getIconHeight() {
    return dim.height;
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2d = (Graphics2D) g;
    g2d.setPaint(c.getBackground());
    g2d.fillRect(x, y, getIconWidth(), getIconHeight());
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                         RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setColor(cColor);
    float alpha = 0.0f;
    Iterator it = list.iterator();
    g2d.translate(x, y);
    while(it.hasNext()) {
      alpha = isRunning?alpha+0.1f:0.5f;
      g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
      g2d.fill((Shape)it.next());
    }
    g2d.translate(-x, -y);
  }
  public void next() {
    if(isRunning) list.addElement(list.remove(0));
  }
  public void setRunning(boolean isRunning) {
    this.isRunning = isRunning;
  }
}
}}
-&jnlp;
-&jar;
-&zip;

**解説 [#md0e801a]
上記のサンプルでは、円のアルファ値が変化するFireFox風のアニメーションアイコンを作成しています。
上記のサンプルでは、スタートボタンを押すと((JTextAreaに表示している作業状況はダミーで、実際はThread.sleep()で時間を稼いでいるだけです))アイコンがFireFox風にアニメーションします。

JTextAreaに表示している作業状況はダミーで、実際はThread.sleep()で時間を稼いでいるだけです。
アニメーションは、8個の円からアイコンを生成して、それぞれのインデックスを順に変更することで行っています。
- アイコンの生成
-- リスト(Vector)に、座標の異なる円(Ellipse2D.Double)を8個生成して追加します。
- インデックスの変更
-- Timerを使って、リストの先頭にある円を最後に移動します。
- 異なるアルファ値で円を描画
-- インデックスに応じたアルファ値でそれぞれの円を描画します。

円がいびつだったので、アンチエイリアスをかけています。Java SE 6 では、「小さな円(曲線)が円に見えなかった問題」が解消されているようです([[参考>http://www.02.246.ne.jp/~torutk/jvm/mustang.html#SEC26]])。
円がいびつだったので、アンチエイリアスをかけていまが、Java SE 6 では「小さな円(曲線)が円に見えなかった問題」が解消されているようです([[参考>http://www.02.246.ne.jp/~torutk/jvm/mustang.html#SEC26]])。

//**参考リンク
**コメント [#o8846e0b]
- 色の濃い円が時計回りに回転するように変更しました。 -- [[terai]] &new{2006-03-15 (水) 11:12:08};

#comment