Samples > Samples GIFアニメーションを表示するカスタムCanvasクラス

 

GIFアニメーションを表示するカスタムCanvasクラス

GIFアニメーションを表示するウィジェットです。Canvasクラスを継承して作ったクラスにGIFアニメーションをスレッドで表示するための仕組みを実装してあります。使い方は、GIFCanvasのコンストラクタにファイル名を指定してインスタンスを生成し、startAnimation()、stopAnimation()でGIFアニメーションの開始と停止を行えます。

GIFCanvas c = new GIFCanvas(shell, SWT.NONE, "earth.gif");
c.startAnimation();
c.stopAnimation();

スクリーンショット

ソースコード (GIFCanvasTest.java)

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class GIFCanvasTest {
        private GIFCanvas gifc1;
        public static void main(String[] args) {
                new GIFCanvasTest();
        }
        public GIFCanvasTest() {
                Display display = new Display();
                Shell shell = new Shell(display);
                shell.setText("GIFCanvasTest");

                shell.setLayout(new GridLayout(3, false));
                
                gifc1 = new GIFCanvas(shell, SWT.BORDER, "earth.gif");
                Button startButton1 = new Button(shell, SWT.PUSH);
                startButton1.setText("Start");
                startButton1.addSelectionListener(new SelectionAdapter(){
                        public void widgetSelected(SelectionEvent e) {
                                gifc1.startAnimation();
                        }
                });
                
                Button stopButton1 = new Button(shell, SWT.PUSH);
                stopButton1.setText("Stop");
                stopButton1.addSelectionListener(new SelectionAdapter(){
                        public void widgetSelected(SelectionEvent e) {
                                gifc1.stopAnimation();
                        }
                });
                                
                shell.pack();
                shell.open();
                while (!shell.isDisposed()) {
                        if (!display.readAndDispatch()) {
                                display.sleep();
                        }
                }
                display.dispose();
        }
}

ソースコード (GIFCanvas.java)

import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

public class GIFCanvas extends Canvas {

        private boolean isRunning = false;
        private ImageLoader loader;
        private GC canvasGC;
        private Display display;
        private int width;
        private int height;
        private Image initialImage;
        private int imageDataIndex = 0;
        private Thread thread = null;
        private Image image;

        public GIFCanvas(Composite parent, int style, String filename) {
                super(parent, style);
                loader = new ImageLoader();
                loader.load(filename);
                width = loader.logicalScreenWidth;
                height = loader.logicalScreenHeight;
                display = parent.getDisplay();

                canvasGC = new GC(this);

                initialImage = new Image(display, loader.data[0]);

                addPaintListener(new PaintListener() {
                        public void paintControl(PaintEvent e) {
                                e.gc.setBackground(getBackground());
                                e.gc.fillRectangle(0, 0, width, height);
                                e.gc.drawImage(initialImage, 0, 0);
                        }
                });
                
                Shell shell = parent.getShell();
                shell.addShellListener(new ShellAdapter(){
                        public void shellClosed(ShellEvent e) {
                                isRunning = false;
                                if (thread != null) {
                                   while (thread.isAlive()) {
                                           if (!display.readAndDispatch()) display.sleep();
                                   }
                                }
                                e.doit = true;
                        }
                });
        }

        public synchronized void startAnimation() {
                if (isRunning) {
                        return;
                }
                isRunning = true;
                thread = new AnimationThread();
                thread.start();

        }

        public synchronized void stopAnimation() {
                isRunning = false;
        }



        public synchronized void dispose() {
                isRunning = false; // stop any animation in progress
                if (image != null){
                        image.dispose();
                }
                if (canvasGC != null){
                        canvasGC.dispose();
                }
                initialImage.dispose();
                super.dispose();
        }

        public Point computeSize(int wHint, int hHint, boolean changed) {
                return super.computeSize(width, height, changed);
        }
        
        class AnimationThread extends Thread {

                public void run() {
                        int numImage = loader.data.length;

                        //repeatCountを使う場合に必要
                        //int repeatCount = loader.repeatCount;

                        int width = loader.logicalScreenWidth;
                        int height = loader.logicalScreenHeight;

                        Image offScreenImage = new Image(display, width, height);
                        GC offScreenImageGC = new GC(offScreenImage);

                        Color bgcolor = canvasGC.getBackground();
                        offScreenImageGC.setBackground(bgcolor);
                        offScreenImageGC.fillRectangle(0, 0, width, height);

                        try {
                                while (isRunning) {
                                   ImageData imageData = loader.data[imageDataIndex];
                                   image = new Image(display, imageData);

                                   offScreenImageGC.drawImage(image, imageData.x, imageData.y);

                                   canvasGC.drawImage(offScreenImage, 0, 0);

                                   //それぞれイメージには遅延時間が設定されており
                                   //その時間だけ待機する
                                   int delayTime = loader.data[imageDataIndex].delayTime;
                                   //設定された遅延時間が短すぎる場合
                                   if (delayTime < 100){
                                           delayTime = 100;
                                   }
                                       
                                   try {
                                           Thread.sleep(delayTime);
                                   } catch (InterruptedException e) {
                                           e.printStackTrace();
                                   }

                                   if (imageDataIndex == numImage - 1) {
                                           imageDataIndex = 0;
                                   } else {
                                           imageDataIndex++;
                                   }
                                }
                        } finally {
                                offScreenImage.dispose();
                                offScreenImageGC.dispose();
                        }
                }
        }
}

参考リンク

以下のリンクに、GIFファイルの特徴や、GIFがどのようなデータ構造を持っているかなどの詳しい解説があります。

 

Copyright(C) 2003,2004 Jasmin Project. All Right Reserved.
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送