SWT 显示动态图片gif

站在巨人的肩膀上: http://blog.csdn.net/xcl119xcl/archive/2010/01/22/5224444.aspx

因为SWT的ImageLoader支持读写以上所有格式的图片,所以实现起来比较简单。主要解决了两个问题。第一个问题是播放GIF动画,通过 ImageLoader读入GIF的所有帧以及间隔时间,然后用Display.timerExec实现Timer播放。第二个问题是对图片的 Scrollbar支持以及pack支持。SWT.H_SCROLL和SWT.V_SCROLL 虽然加上了滚动条,但是不起作用,需要监听滚动条的SWT.Selection事件。另外,加上滚动条后,pack无法得到大小,不能正确的pack。需要重载computeSize。


/** 
 * 负责显示各种格式的图片
 * 
 *  @author 喜来乐哈哈
  */ 
public   class  ImageViewer  extends  Canvas {

     protected  Point origin  =   new  Point( 0 ,  0 );
     protected  Image image;
     protected  ImageData[] imageDatas;
     protected  Image[] images;
     protected   int  current;

     private   int  repeatCount;
     private  Runnable animationTimer;
     private  ScrollBar hBar;
     private  ScrollBar vBar;
     private  Color bg;
     private  Display display;

     public  ImageViewer(Composite parent) {
         super (parent, SWT.NO_BACKGROUND  |  SWT.NO_REDRAW_RESIZE  |  SWT.V_SCROLL
                 |  SWT.H_SCROLL);

        hBar  =  getHorizontalBar();
        vBar  =  getVerticalBar();
        bg  =  getBackground();
        display  =  getDisplay();
        addListeners();
    }

     public   void  setImage(ImageData imageData) {
        checkWidget();

        stopAnimationTimer();
         this .image  =   new  Image(display, imageData);
         this .imageDatas  =   null ;
         this .images  =   null ;
        redraw();
    }

     /** 
     *  @param  repeatCount 0 forever
      */ 
     public   void  setImages(ImageData[] imageDatas,  int  repeatCount) {
        checkWidget();

         this .image  =   null ;
         this .imageDatas  =  imageDatas;
         this .repeatCount  =  repeatCount;
        convertImageDatasToImages();
        startAnimationTimer();
        redraw();
    }

    @Override
     public  Point computeSize( int  wHint,  int  hHint,  boolean  changed) {
        checkWidget();

        Image image  =  getCurrentImage();
         if  (image  !=   null ) {
            Rectangle rect  =  image.getBounds();
            Rectangle trim  =  computeTrim( 0 ,  0 , rect.width, rect.height);
             return   new  Point(trim.width, trim.height);
        }

         return   new  Point(wHint, hHint);
    }

    @Override
     public   void  dispose() {
         if  (image  !=   null )
            image.dispose();

         if  (images  !=   null )
             for  ( int  i  =   0 ; i  <  images.length; i ++ )
                images[i].dispose();

         super .dispose();
    }

     protected   void  paint(Event e) {
        Image image  =  getCurrentImage();
         if  (image  ==   null )
             return ;

        GC gc  =  e.gc;
        gc.drawImage(image, origin.x, origin.y);

        gc.setBackground(bg);
        Rectangle rect  =  image.getBounds();
        Rectangle client  =  getClientArea();
         int  marginWidth  =  client.width  -  rect.width;
         if  (marginWidth  >   0 ) {
            gc.fillRectangle(rect.width,  0 , marginWidth, client.height);
        }
         int  marginHeight  =  client.height  -  rect.height;
         if  (marginHeight  >   0 ) {
            gc.fillRectangle( 0 , rect.height, client.width, marginHeight);
        }
    }

     void  addListeners() {
        hBar.addListener(SWT.Selection,  new  Listener() {
             public   void  handleEvent(Event arg0) {
                hscroll();
            }
        });
        vBar.addListener(SWT.Selection,  new  Listener() {
             public   void  handleEvent(Event arg0) {
                vscroll();
            }
        });
        addListener(SWT.Resize,  new  Listener() {
             public   void  handleEvent(Event e) {
                resize();
            }
        });
        addListener(SWT.Paint,  new  Listener() {
             public   void  handleEvent(Event e) {
                paint(e);
            }
        });
    }

     void  hscroll() {
        Image image  =  getCurrentImage();
         if  (image  !=   null ) {
             int  hSelection  =  hBar.getSelection();
             int  destX  =   - hSelection  -  origin.x;
            Rectangle rect  =  image.getBounds();
            scroll(destX,  0 ,  0 ,  0 , rect.width, rect.height,  false );
            origin.x  =   - hSelection;
        }
    }

     void  vscroll() {
        Image image  =  getCurrentImage();
         if  (image  !=   null ) {
             int  vSelection  =  vBar.getSelection();
             int  destY  =   - vSelection  -  origin.y;
            Rectangle rect  =  image.getBounds();
            scroll( 0 , destY,  0 ,  0 , rect.width, rect.height,  false );
            origin.y  =   - vSelection;
        }
    }

     void  resize() {
        Image image  =  getCurrentImage();
         if  (image  ==   null )
             return ;

        Rectangle rect  =  image.getBounds();
        Rectangle client  =  getClientArea();
        hBar.setMaximum(rect.width);
        vBar.setMaximum(rect.height);
        hBar.setThumb(Math.min(rect.width, client.width));
        vBar.setThumb(Math.min(rect.height, client.height));
         int  hPage  =  rect.width  -  client.width;
         int  vPage  =  rect.height  -  client.height;
         int  hSelection  =  hBar.getSelection();
         int  vSelection  =  vBar.getSelection();
         if  (hSelection  >=  hPage) {
             if  (hPage  <=   0 )
                hSelection  =   0 ;
            origin.x  =   - hSelection;
        }
         if  (vSelection  >=  vPage) {
             if  (vPage  <=   0 )
                vSelection  =   0 ;
            origin.y  =   - vSelection;
        }
        redraw();
    }

     void  convertImageDatasToImages() {
        images  =   new  Image[imageDatas.length];

         //  Step 1: Determine the size of the resulting images. 
         int  width  =  imageDatas[ 0 ].width;
         int  height  =  imageDatas[ 0 ].height;

         //  Step 2: Construct each image. 
         int  transition  =  SWT.DM_FILL_BACKGROUND;
         for  ( int  i  =   0 ; i  <  imageDatas.length; i ++ ) {
            ImageData id  =  imageDatas[i];
            images[i]  =   new  Image(display, width, height);
            GC gc  =   new  GC(images[i]);

             //  Do the transition from the previous image. 
             switch  (transition) {
             case  SWT.DM_FILL_NONE:
             case  SWT.DM_UNSPECIFIED:
                 //  Start from last image. 
                gc.drawImage(images[i  -   1 ],  0 ,  0 );
                 break ;
             case  SWT.DM_FILL_PREVIOUS:
                 //  Start from second last image. 
                gc.drawImage(images[i  -   2 ],  0 ,  0 );
                 break ;
             default :
                 //  DM_FILL_BACKGROUND or anything else,
                 //  just fill with default background. 
                gc.setBackground(bg);
                gc.fillRectangle( 0 ,  0 , width, height);
                 break ;
            }

             //  Draw the current image and clean up. 
            Image img  =   new  Image(display, id);
            gc.drawImage(img,  0 ,  0 , id.width, id.height, id.x, id.y, id.width,
                    id.height);
            img.dispose();
            gc.dispose();

             //  Compute the next transition.
             //  Special case: Can't do DM_FILL_PREVIOUS on the
             //  second image since there is no "second last"
             //  image to use. 
            transition  =  id.disposalMethod;
             if  (i  ==   0   &&  transition  ==  SWT.DM_FILL_PREVIOUS)
                transition  =  SWT.DM_FILL_NONE;
        }
    }

    Image getCurrentImage() {
         if  (image  !=   null )
             return  image;

         if  (images  ==   null )
             return   null ;

         return  images[current];
    }

     void  startAnimationTimer() {
         if  (images  ==   null   ||  images.length  <   2 )
             return ;

         final   int  delay  =  imageDatas[current].delayTime  *   10 ;
        display.timerExec(delay, animationTimer  =   new  Runnable() {
             public   void  run() {
                 if  (isDisposed())
                     return ;

                current  =  (current  +   1 )  %  images.length;
                redraw();

                 if  (current  +   1   ==  images.length  &&  repeatCount  !=   0 
                         &&   -- repeatCount  <=   0 )
                     return ;
                display.timerExec(delay,  this );
            }
        });
    }

     void  stopAnimationTimer() {
         if  (animationTimer  !=   null )
            display.timerExec( - 1 , animationTimer);
    }
} 


测试程序

public   class  ImageCanvasTest {
     public   static   void  main(String[] args) {
        Display display  =   new  Display();
         final  Shell shell  =   new  Shell(display);
        ImageViewer ic  =   new  ImageViewer(shell);

        shell.setLayout( new  FillLayout());
        FileDialog dialog  =   new  FileDialog(shell, SWT.OPEN);
        dialog.setText( " Open an image file or cancel " );
        String string  =  dialog.open();

        ImageLoader loader  =   new  ImageLoader();
        ImageData[] imageDatas  =  loader.load(string);
         if  (imageDatas.length  ==   0 )
             return ;
         else   if  (imageDatas.length  ==   1 ) {
            ic.setImage(imageDatas[ 0 ]);
        }  else  {
            ic.setImages(imageDatas, loader.repeatCount);
        }

        ic.pack();
        shell.pack();
        shell.open();
         while  ( ! shell.isDisposed()) {
             if  ( ! display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }
} 

在对GIF图片的支持上,Swing要做的好很多,一句label.setIcon(new ImageIcon(name))就搞定GIF动画了。

你可能感兴趣的:(.net,swing,Blog,UP)