gr8vyguy@Blogjava

SWT图片显示,支持JPEG,GIF(动画),BMP,ICO,PNG和TIFF

因为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(00);
    
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(00, 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, 
000, 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, 00, 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], 00);
                
break;
            
case SWT.DM_FILL_PREVIOUS:
                
// Start from second last image.
                gc.drawImage(images[i - 2], 00);
                
break;
            
default:
                
// DM_FILL_BACKGROUND or anything else,
                
// just fill with default background.
                gc.setBackground(bg);
                gc.fillRectangle(
00, width, height);
                
break;
            }

            
// Draw the current image and clean up.
            Image img = new Image(display, id);
            gc.drawImage(img, 
00, 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动画了。

转载请保留http://www.blogjava.net/xilaile/archive/2007/04/10/109547.html

posted on 2007-04-10 00:33 gr8vyguy 阅读(9308) 评论(3)  编辑  收藏 所属分类: Java

评论

# re: SWT图片显示,支持JPEG,GIF(动画),BMP,ICO,PNG和TIFF 2007-04-10 03:08 BeanSoft

友情赞助一下, 我用的是http://www.eclipse.org/articles/Article-Image-Viewer/Image_viewer.html 的一个叫 Chengdong Li (cdli@ccs.uky.edu) 的华裔写的. 不过没试对动画GIF的支持如何.  回复  更多评论   

# re: SWT图片显示,支持JPEG,GIF(动画),BMP,ICO,PNG和TIFF 2007-04-28 13:06 Pande

谢了,我看了,它的那个对GIF不支持,不过它用了ScrollableComposite倒是个好主意  回复  更多评论   

# re: SWT图片显示,支持JPEG,GIF(动画),BMP,ICO,PNG和TIFF 2010-01-14 05:49 yangerran

这个写的非常好,我试了,不错  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2007年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

导航

统计

公告

  • 转载请注明出处.
  • msn: gr8vyguy at live.com
  • 常用链接

    留言簿(9)

    随笔分类(68)

    随笔档案(80)

    文章分类(1)

    My Open Source Projects

    搜索

    积分与排名

    最新评论