java swt 之 图片控件
swt好像加载动态gif也得需要自己让图片跑起来,找了很长时间找到一份源码,改了改,让它更原本一点。
使用的话,注意gif帧速的变量,可以自己多调试调试,gif在不同的平台上速度是不一样的,就像那个跑疯了的手机测试gif一样。
package atomQQswt.ui.core;
import java.io.InputStream;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Listener;
public class ImageCanvas extends Canvas {
private ImageLoader loader;
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 Color bg;
private Display display;
public ImageCanvas(Composite parent) {
super(parent, SWT.DOUBLE_BUFFERED | SWT.INHERIT_FORCE |SWT.INHERIT_DEFAULT);
bg = getBackground();
display = getDisplay();
addListeners();
}
/**
* 传入路径获取图片.
*
* @param path the new image
*/
public void setImage(String path){
loader = new ImageLoader();
imageDatas = loader.load(path);
if(imageDatas.length == 0)
return;
else if(imageDatas.length == 1){
checkWidget();
stopAnimationTimer();
this.image = new Image(display, imageDatas[0]);
this.imageDatas = null;
this.images = null;
redraw();
}else {
checkWidget();
this.image = null;
this.repeatCount = loader.repeatCount;
convertImageDatasToImages();
startAnimationTimer();
redraw();
}
}
/**
* 传入InputStream获取图片.
*
* @param isin the new image
*/
public void setImage(InputStream isin){
loader = new ImageLoader();
imageDatas = loader.load(isin);
if(imageDatas.length == 0)
return;
else if(imageDatas.length == 1){
checkWidget();
stopAnimationTimer();
this.image = new Image(display, imageDatas[0]);
this.imageDatas = null;
this.images = null;
redraw();
}else {
checkWidget();
this.image = null;
this.repeatCount = loader.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() {
addListener(SWT.Paint, new Listener() {
public void handleEvent(Event e) {
paint(e);
}
});
}
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;
int delay = imageDatas[current].delayTime*20;
if (delay <5) delay = 100;
final int ms=delay;
display.timerExec(ms, 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(ms, this);
}
});
}
void stopAnimationTimer() {
if (animationTimer != null)
display.timerExec(-1, animationTimer);
}
}
import java.io.InputStream;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Listener;
public class ImageCanvas extends Canvas {
private ImageLoader loader;
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 Color bg;
private Display display;
public ImageCanvas(Composite parent) {
super(parent, SWT.DOUBLE_BUFFERED | SWT.INHERIT_FORCE |SWT.INHERIT_DEFAULT);
bg = getBackground();
display = getDisplay();
addListeners();
}
/**
* 传入路径获取图片.
*
* @param path the new image
*/
public void setImage(String path){
loader = new ImageLoader();
imageDatas = loader.load(path);
if(imageDatas.length == 0)
return;
else if(imageDatas.length == 1){
checkWidget();
stopAnimationTimer();
this.image = new Image(display, imageDatas[0]);
this.imageDatas = null;
this.images = null;
redraw();
}else {
checkWidget();
this.image = null;
this.repeatCount = loader.repeatCount;
convertImageDatasToImages();
startAnimationTimer();
redraw();
}
}
/**
* 传入InputStream获取图片.
*
* @param isin the new image
*/
public void setImage(InputStream isin){
loader = new ImageLoader();
imageDatas = loader.load(isin);
if(imageDatas.length == 0)
return;
else if(imageDatas.length == 1){
checkWidget();
stopAnimationTimer();
this.image = new Image(display, imageDatas[0]);
this.imageDatas = null;
this.images = null;
redraw();
}else {
checkWidget();
this.image = null;
this.repeatCount = loader.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() {
addListener(SWT.Paint, new Listener() {
public void handleEvent(Event e) {
paint(e);
}
});
}
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;
int delay = imageDatas[current].delayTime*20;
if (delay <5) delay = 100;
final int ms=delay;
display.timerExec(ms, 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(ms, this);
}
});
}
void stopAnimationTimer() {
if (animationTimer != null)
display.timerExec(-1, animationTimer);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述