来源:http://www.blogjava.net/xilaile/archive/2007/04/10/109547.html
因为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();
}
}
分享到:
相关推荐
ImageViewer ActiveX控件 是一个ActiveX 控件,您可以利用它在您开发的程序中集成图片浏览功能,支持大部分常见的图片格式,可用于Microsoft Visual Studio,Microsoft Office 和 Borland Delphi。 <br> ...
Image Viewer CP ActiveX控件 是一个很小的图像阅览插件,它支持常用图像文件格式,包括BMP、 GIF、JPEG、PNG、ICO和TIFF。 <br> Image Viewer CP ActiveX控件产品特色: 可以调整图像大小并可以导出JPEG、...
Image Viewer .NET旨在替代Windows 7内置图片查看器,因为该程序会自动更改图片而无需询问用户。 相反,Image Viewer .NET不执行任何类型的更改。 此外,Image Viewer .NET提供了应用其他与图片相关的信息的功能,并...
A shareware image viewer application(36KB)
图像浏览器 具有缩放,移动功能的图像显示控件。
图像浏览器 图像查看器(WPF)。 语言C#和WPF。 平台.Net 4.5 职能: 查看文件夹中的图像 带有动画的幻灯片放映 皮肤 资料夹导览 全屏观看 [项目]-MS Visual Studio 2012项目 [src]-仅资源和资源
ImageViewer关于图片浏览器,支持图片手势缩放、拖拽等操作,自定义View的模式显示,自定义图片加载方式,可自定义索引UI、ProgressView,更加灵活,易于扩展,同时也适用于RecyclerView、ListView的横向和纵向列表...
Qt6 QML Book/QtQuick控件/图像查看器 示例源码 CSDN审核可能较慢,如无法下载,可以过段时间再回来看下 仅供相关爱好者交流使用,请于下载24小时内删除
✓图像居中✓设置背景色✓图像相对于鼠标光标的缩放✓图像相对于鼠标光标的旋转✓鼠标平移✓垂直滚动✓水平滚动✓旋转和滚动键映射✓滚动条隐藏✓...图像查看器✓适用于本地文件和隐身模式默认控件(在选项页面中可见)...
✓图像居中✓设置背景色✓图像相对于鼠标光标的缩放✓图像相对于鼠标光标的旋转✓鼠标平移✓垂直滚动✓水平滚动✓旋转和滚动键映射✓滚动条隐藏✓...图像查看器✓适用于本地文件和隐身模式默认控件(在选项页面中可见)...
Viscom.Image.Viewer.CP.Pro.ActiveX.Control.v1.3.WinALL.Retail.是一个 ActiveX 插件程序,它能够读取、保存和转换图像文件,而且 Image Viewer CP Pro Control 还可以与任何语言的,支持 ActiveX 技术的程序设计...
#QtCustomWidgets 说明格式如下: 项目名称 编译环境 运行截图 注意事项 ...#ImageViewer 旋转的圆 编译环境: Qt5.x + mingw-QtCreater 运行截图: #CurveChart 简单曲线图 编译环境: Qt5.x + mingw-QtCreater 运行截图:
jpeg控件,可用于j查看epg2000,jp2,适用于pb,vb,vc++,含有licence. imageviewer.lic ImageViewer2.OCX
ImageViewer是一个功能强大的图像查看器控件只使用FravaLoeStand,将属性流向FlowDirection.LeftToRight设置,就是这样。 如果您想了解更多关于锚定和对接的信息,请看如何:在FLULLAOTHOPAND控件中锚定和停靠子控件...
MFC图片查看示例程序,通过CImage类打开bmp、jpg、PNG等常规格式的图片,通过StretchBlt提取缩略图,并加载至ListCtrl控件。通过静态控件预览所选缩略图的大图。
默认显示控件。 让它们立即淡出。 鼠标移动时短暂显示控件。 双控制(最小和最大) 使控件成为布尔值。 通过单击图像在最小值和最大值之间切换。 因此已经重新实现了 chrome 的工具。 创建设置页面。 使用响应 ...
A powerful and versatile auto image browser and viewer.
Android通过ImageView控件实现图片资源的显示,通过Button控制上一张、下一张图片的切换
DICOM_ImageViewer 影像浏览 影像浏览器 DICOM_FilmBox 胶片打印 所见即所得的胶片打印功能 DICOM_IconBar 图标栏 把影像浏览器和胶片打印联系起来 DICOM_3DDataStore 体数据容器 存放经过预处理的影像数据 ...
一套开发网络相关程序...支持 FTPS、SMTPS、HTTPS、POP3S、NNTP、TelnetS、Gopher、Image Viewer、MIME、Ping、RCMD、DNS、RAS、SocketWrench/Winsock、Terminal Emulator、Finger、Audio Player、Time、Whois等。