|
|
站在巨人的肩膀上: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.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; images = new Image(display, width, height); GC gc = new GC(images); // 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动画了。 |
|