使用SWT实现图片预览
工作中需要使用swt进行需求开发:给出一组图片,能够预览等其他操作。
将图片预览相关代码单独拿出,创建测试项目,能够实现根据行列数创建图片展示窗口,并能够自适应窗口大小及图片居中,异步添加图片不阻塞窗口等功能。记录起来供今后或他人参考。
-
首先列出效果图
封装了一个用于展示图片的类,根据构造方法可以设置显示的行数及列数。根据设置的宽高进行自适应,可以实现滚动条,选择,查看,全选,反选,图片大小自适应等其他操作。 -
封装类代码
package name.hanenhao.ui;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import name.hanenhao.entity.FileMeta;
public class ImageViewer extends ScrolledComposite {
int width = 433;
int height = 335;
ImageViewer imageViewer = this;
ImageDraw imageDraw;
private Composite composite;
// 水平滚动条
private ScrollBar horizontalBar = this.getHorizontalBar();
// 垂直滚动条
private ScrollBar verticalBar = this.getVerticalBar();
private ExecutorService executorService = Executors.newSingleThreadExecutor();
List<ImageDraw> imageDraws = Collections.synchronizedList(new ArrayList<ImageDraw>());
int xCount;
int yCount;
public ImageViewer(Composite parent, int style) {
this(parent, style, 2, 2);
}
public ImageViewer(Composite parent, int style, int xCount, int yCount) {
// 样式不能为0 否则不会创建滚动条
super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
this.setLayout(new FillLayout());
this.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
composite = new Composite(this, SWT.NONE);
composite.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
this.setContent(composite);
RowLayout layout = new RowLayout();
composite.setLayout(layout);
horizontalBar.setIncrement(15);
verticalBar.setIncrement(15);
this.compositeComputeSize();
this.xCount = xCount;
this.yCount = yCount;
}
public List<ImageDraw> getImageDraws(Boolean isCheck) {
if (isCheck == null) {
return this.imageDraws;
}
List<ImageDraw> draws = new ArrayList<ImageViewer.ImageDraw>();
for (ImageDraw draw : imageDraws) {
if (draw.checkBox.getSelection() == isCheck) {
draws.add(draw);
}
}
return draws;
}
public int count(Boolean isCheck) {
if (isCheck == null) {
return this.imageDraws.size();
}
int size = 0;
for (ImageDraw draw : imageDraws) {
if (draw.checkBox.getSelection() == isCheck) {
size++;
}
}
return size;
}
public List<String> getFileIds(Boolean isCheck) {
List<String> fileIdOrNames = new ArrayList<String>();
for (ImageDraw draw : imageDraws) {
if (isCheck == null) {
String id = getId(draw);
if (id != null) {
fileIdOrNames.add(id);
}
continue;
}
if (draw.checkBox.getSelection() == isCheck) {
String id = getId(draw);
if (id != null) {
fileIdOrNames.add(id);
}
}
}
return fileIdOrNames;
}
List<String> getSelectFile() {
return getFileIds(true);
}
List<FileMeta> getFileMetaDatas(Boolean isCheck) {
List<FileMeta> fileMetas = new ArrayList<FileMeta>();
for (ImageDraw draw : imageDraws) {
if (isCheck == null) {
fileMetas.add(draw.data);
continue;
}
if (draw.checkBox.getSelection() == isCheck) {
fileMetas.add(draw.data);
}
}
return fileMetas;
}
List<String> remove() {
List<String> fileIdOrNames = new ArrayList<String>();
List<ImageDraw> disposeImageDraws = new ArrayList<ImageViewer.ImageDraw>();
for (ImageDraw draw : imageDraws) {
if (draw.checkBox.getSelection()) {
fileIdOrNames.add(getId(draw));
draw.dispose();
disposeImageDraws.add(draw);
}
}
if (fileIdOrNames.size() == 0) {
popup("未选择文件");
}
imageDraws.removeAll(disposeImageDraws);
compositeComputeSize();
return fileIdOrNames;
}
void clear() {
for (ImageDraw draw : imageDraws) {
draw.dispose();
}
imageDraws.clear();
composite.setSize(0, 0);
composite.layout();
}
public void addImage(String path, FileMeta data) throws MalformedURLException {
addImage(new URL(path), data);
}
public void addImage(URL url, FileMeta data) {
ImageDraw draw = new ImageDraw(composite, url, data);
this.imageDraws.add(draw);
compositeComputeSize();
this.setFocus();
draw.update();
}
public void addImage(File file, FileMeta fileMeta) {
try {
addImage(file.toURI().toURL(), fileMeta);
} catch (RuntimeException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void asycnAddImage(final File file, final FileMeta fileMeta) {
try {
asycnAddImage(file.toURI().toURL(), fileMeta);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void asycnAddImage(URL url, final FileMeta fileMeta) {
executorService.execute(new Runnable() {
@Override
public void run() {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
imageViewer.addImage(url, fileMeta);
}
});
}
});
}
List<String> exportImages() {
List<String> fileNames = new ArrayList<String>();
for (ImageDraw draw : imageDraws) {
if (draw.checkBox.getSelection()) {
fileNames.add(getId(draw));
}
}
return fileNames;
}
void checkAll() {
for (ImageDraw draw : imageDraws) {
draw.checkBox.setSelection(true);
}
}
void unCheckAll() {
for (ImageDraw draw : imageDraws) {
draw.checkBox.setSelection(false);
}
}
// 将图片转换为特定格式 tip
File swap() throws Throwable {
/*
* List<FileMeta> fileMetas = this.getFileMetaDatas(true); if
* (!(fileMetas.size() > 1)) { return null; } List<File> files = new
* ArrayList<File>(); for (FileMeta fileMeta : fileMetas) { String fileName =
* fileMeta.getEntry(CWXConstants.KEY_FILE_NAME); if (fileName.endsWith(".pdf"))
* { throw new Throwable("pdf图片不能再次合并"); } File file =
* FileUtil.getFile(fileName); files.add(file); } File target =
* PdfUtil.imagesToPdf(files, FileUtil.getBatchPath()); FileMeta fileMeta = new
* FileMeta(); fileMeta.getEntries().put(CWXConstants.KEY_FILE_NAME,
* target.getName()); fileMeta.setFiletype("pdf");
* fileMeta.setFiletype(target.getAbsolutePath());
* fileMeta.setGenerateTime(FileUtil.getNowTime()); this.addImage(target,
* fileMeta); this.remove();
*/
return null;
}
void inverse() {
for (ImageDraw draw : imageDraws) {
draw.checkBox.setSelection(!draw.checkBox.getSelection());
}
}
void left() {
for (ImageDraw draw : imageDraws) {
if (draw.checkBox.getSelection()) {
// draw.file = left(draw.image);
draw.redraw();
}
}
}
void right() {
for (ImageDraw draw : imageDraws) {
if (draw.checkBox.getSelection()) {
// draw.image = right(draw.image);
draw.redraw();
}
}
}
@SuppressWarnings("unused")
private Image right(Image image) {
if (image != null) {
ImageData srcData = image.getImageData();
int bytesPerPixel = srcData.bytesPerLine / srcData.width;
int destBytesPerLine = srcData.height * bytesPerPixel;
byte[] newData = new byte[srcData.data.length];
int width = 0, height = 0;
for (int srcY = 0; srcY < srcData.height; srcY++) {
for (int srcX = 0; srcX < srcData.width; srcX++) {
int destX = 0, destY = 0, destIndex = 0, srcIndex = 0;
destX = srcData.height - srcY - 1;
destY = srcX;
width = srcData.height;
height = srcData.width;
destIndex = (destY * destBytesPerLine) + (destX * bytesPerPixel);
srcIndex = (srcY * srcData.bytesPerLine) + (srcX * bytesPerPixel);
System.arraycopy(srcData.data, srcIndex, newData, destIndex, bytesPerPixel);
}
}
ImageData targData = new ImageData(width, height, srcData.depth, srcData.palette, destBytesPerLine,
newData);
image = new Image(null, targData);
}
return image;
}
@SuppressWarnings("unused")
private Image left(Image image) {
if (image != null) {
ImageData srcData = image.getImageData();
int bytesPerPixel = srcData.bytesPerLine / srcData.width;
int destBytesPerLine = srcData.height * bytesPerPixel;
byte[] newData = new byte[srcData.data.length];
int width = 0, height = 0;
for (int srcY = 0; srcY < srcData.height; srcY++) {
for (int srcX = 0; srcX < srcData.width; srcX++) {
int destX = 0, destY = 0, destIndex = 0, srcIndex = 0;
destX = srcY;
destY = srcData.width - srcX - 1;
width = srcData.height;
height = srcData.width;
destIndex = (destY * destBytesPerLine) + (destX * bytesPerPixel);
srcIndex = (srcY * srcData.bytesPerLine) + (srcX * bytesPerPixel);
System.arraycopy(srcData.data, srcIndex, newData, destIndex, bytesPerPixel);
}
}
ImageData targData = new ImageData(width, height, srcData.depth, srcData.palette, destBytesPerLine,
newData);
image = new Image(null, targData);
}
return image;
}
private String getId(ImageDraw draw) {
if (draw == null || draw.data == null) {
return null;
}
FileMeta fileMeta = draw.data;
String fileId = fileMeta.getId();
String fileName = fileMeta.getName();
return fileId != null ? fileId : fileName;
}
void compositeComputeSize() {
int width = 0;
Object obj = this.getLayout();
if (obj instanceof RowLayout) {
RowData rowData = (RowData) this.getLayoutData();
width = rowData.width;
} else if (obj instanceof GridLayout) {
GridData gridData = (GridData) this.getLayoutData();
width = gridData.widthHint;
} else {
width = this.getSize().x;
}
Point point = composite.computeSize(width - verticalBar.getSize().x, SWT.DEFAULT);
composite.setSize(point.x, point.y + 20);
composite.layout();
}
// 储存宽高
@Override
public void setSize(int width, int height) {
this.width = width;
this.height = height;
this.compositeComputeSize();
super.setSize(width, height);
}
@Override
public void setBounds(int x, int y, int width, int height) {
this.width = width;
this.height = height;
this.compositeComputeSize();
super.setBounds(x, y, width, height);
}
// 计算水平空隙宽度
public int getVerticalSpace() {
RowLayout rowLayout = (RowLayout) composite.getLayout();
return rowLayout.marginLeft + rowLayout.marginRight + rowLayout.spacing * 2;
}
// 计算垂直空隙高度
public int getHorizontalSpace() {
RowLayout rowLayout = (RowLayout) composite.getLayout();
return rowLayout.marginTop + rowLayout.marginBottom + rowLayout.spacing * 3;
}
protected SelectionListener getImageDrawCheckEvent() {
SelectionListener selectionListener = new SelectionAdapter() {
};
return selectionListener;
}
protected MouseListener getImageDrawClickEvent() {
MouseListener mouseListener = new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if (e.button == 1) {
ImageDraw imageDraw = (ImageDraw) e.widget;
if (imageDraw.checkBox != null) {
imageDraw.checkBox.setSelection(!imageDraw.checkBox.getSelection());
// 触发check事件
Event event = new Event();
event.widget = imageDraw.checkBox;
event.type = SWT.Selection;
Display.getCurrent().post(event);
imageDraw.checkBox.notifyListeners(SWT.Selection, event);
}
}
}
@Override
public void mouseDoubleClick(MouseEvent e) {
if (e.button == 1) {
try {
File file = new File(imageDraw.url.toURI());
Runtime.getRuntime().exec("rundll32 url.dll FileProtocolHandler " + file.getAbsolutePath());
} catch (URISyntaxException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
};
return mouseListener;
}
/**
* 图片容器,放在imageview中,用于包裹图片以及对图片缩放居中
*/
public class ImageDraw extends Canvas {
private URL url;
private int imageMaxHeight;
private int imageMaxWidth;
FileMeta data;
Button checkBox;
public ImageDraw(Composite parent, URL url, FileMeta data) {
super(parent, SWT.BORDER);
this.url = url;
imageDraw = this;
this.data = data;
imageMaxHeight = computeSize().y * 90 / 100;
imageMaxWidth = imageMaxHeight;
// 设置右键菜单
// this.setMenu(new PopupMenu(this));
Point point = this.computeSize();
this.setLayoutData(new RowData(point.x, point.y));
checkBox = new Button(this, SWT.CHECK);
checkBox.setBounds(point.x - 20, point.y - 20, 20, 20);
// this.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
compositeComputeSize();
// 显示备注
/*
* if (data != null && data.getEntry("Comments") != null) {
*
* }
*/
registryEvents();
}
/**
* 计算每个draw宽高
*/
protected Point computeSize() {
int x = (imageViewer.getSize().x - verticalBar.getSize().x - getVerticalSpace()) / xCount - 1 * xCount;
int y = (imageViewer.getSize().y - getHorizontalSpace()) / yCount;
return new Point(x, y);
}
protected void painting(PaintEvent arg0) {
InputStream inputStream = null;
try {
inputStream = url.openStream();
Image image = new Image(null, new ImageData(inputStream));
image = zoom(image);
Point point = computeSize();
int x = (point.x - image.getBounds().width) / 2;
int y = (point.y - image.getBounds().height) / 2;
arg0.gc.drawImage(image, x, y);
arg0.gc.dispose();
image.dispose();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void registryEvents() {
this.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent arg0) {
painting(arg0);
}
});
// 注册点击事件
MouseListener mouseListener = getImageDrawClickEvent();
this.addMouseListener(mouseListener);
// 注册选中事件
SelectionListener selectionListener = getImageDrawCheckEvent();
this.checkBox.addSelectionListener(selectionListener);
}
// 缩放并居中 返回缩放后图片
protected Image zoom(Image image) {
Point point = this.computeSize();
int imageDrawWidth = point.x;
int width = image.getBounds().width;
int height = image.getBounds().height;
// log.debug("加载图片大小 width:" + width + " ,height:" + height);
if (width > imageMaxWidth || height > imageMaxHeight) {
double widthRatio = (double) width / (double) imageDrawWidth;
double heightRatio = (double) height / (double) imageMaxHeight;
if (widthRatio >= heightRatio) {
width = imageDrawWidth;
height = (int) (height / widthRatio);
} else {
height = imageMaxHeight;
width = (int) (width / heightRatio);
}
// log.debug("缩放后图片的大小 width:" + width + " ,height:" + height);
if (width == 0) {
width = 1;
}
if (height == 0) {
height = 1;
}
Image image2 = new Image(null, image.getImageData().scaledTo(width, height));
image.dispose();
return image2;
}
return image;
}
public ImageViewer getImageViewer() {
return imageViewer;
}
public FileMeta getData() {
return data;
}
public void setData(FileMeta data) {
this.data = data;
}
}
private void popup(final String msg) {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
Shell s = getShell();
MessageBox messageBox = new MessageBox(s, SWT.NONE);
messageBox.setMessage(msg);
messageBox.setText("提示");
messageBox.open();
}
});
}
}
3.下载地址
swt-demo.zip