把Swing的Icon转换到SWT的Image

简介:
环境:Windows7、Eclipse 3.5、JRE1.6
最近在研究SWT的TreeView控件,想要写一个类似于Windows资源管理器的目录树,弄了半天,目录树是出来了,但是图标搞不出来,何解?FileSystemView.getFileSystemView().getSystemIcon(File f)这个函数返回的是个Icon对象,是用在Swing上的,而我的目录树采用的是SWT/JFace TreeViewer控件,其ILabelProvider的getImage()接口返回的是SWT的Image对象。这两个玩意儿得转换一下才能使用。
在网上找了半天的资料,发现没有现成的API可以一句话就完成转换,都是需要写一段代码来完成。有几个方案,基本思路都是将Icon对象内所包含的Icon数据转换成数据流,然后根据这个数据流重新生成Image,其代码如下:
@Override
public  Image getImage(Object element)
{
     // 得到文件图标
    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);
    java.awt.Image image = systemIcon.getImage();
 
     int  width = image.getWidth( null );
     int  height = image.getHeight( null );
     // 创建用于绘制 Icon 的缓冲区
    BufferedImage bufferedImage =  new  BufferedImage(width, height, BufferedImage. TYPE_INT_RGB );
 
     // 绘制 Icon 到缓冲区
    Graphics2D g2d = bufferedImage.createGraphics();
    g2d.drawImage(image, 0, 0,  null );
    g2d.dispose();
     // 读取缓冲区图片数据到一个数组
     int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
     // 根据数组数据生成 ImageData 对象
    ImageData imageData =  new  ImageData(width, height, 24,  new  PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    imageData.setPixels(0, 0, data. length , data, 0);
     // 生成 Image 对象
    Image swtImage =  new  Image(PlatformUI.getWorkbench().getDisplay(), imageData);
     return  swtImage;
}
Icon的确是转换到Image了,看下面的效果图:
001
虽然Icon转换到了Image,可是图片周围全都是黑色,这是因为Icon在转换的时候,原来的图片里面是透明色的像素点,转换过来系统自动变成了黑色,因此代码还需要额外的处理一下,修改后的代码如下:
@Override
public  Image getImage(Object element)
{
     // 得到文件图标
    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);
    java.awt.Image image = systemIcon.getImage();
 
     int  width = image.getWidth( null );
     int  height = image.getHeight( null );
     // 创建用于绘制 Icon 的缓冲区
    BufferedImage bufferedImage =  new  BufferedImage(width, height, BufferedImage. TYPE_INT_RGB );
 
     // 绘制 Icon 到缓冲区
    Graphics2D g2d = bufferedImage.createGraphics();
    g2d.drawImage(image, 0, 0,  null );
    g2d.dispose();
     // 读取缓冲区图片数据到一个数组
     int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
     // 将没有颜色的点设置为白色
     for  ( int  i = 0; i < data. length ; i++)
    {
     if  (data[i] == 0)
        data[i] = 0xFFFFFF;
    }
     // 根据数组数据生成 ImageData 对象
    ImageData imageData =  new  ImageData(width, height, 24,  new  PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    imageData.setPixels(0, 0, data. length , data, 0);
     // 生成 Image 对象
    Image swtImage =  new  Image(PlatformUI.getWorkbench().getDisplay(), imageData);
     return  swtImage;
}
和上面的代码相比,新增加了一个循环,将缓冲区内为0的数据修改为0xFFFFFF,也就是将相应的像素设置为白色,效果图如下:
002
看起来效果好多了,可是如果目光敏锐一点的话,还是能够看出破绽来,截取一个图标,放大后仔细看一看:
2
和正常的图标对比一下,可以发现边边角角的颜色都不对,普遍偏深,可是网上找到的资料到这里就为止了,没有人提出来如何解决这个问题,当然,这也可能跟我的系统有关系。经过跟踪和调试,发现其实调用 systemIcon.getImage() 得到的对象就已经是一个BufferedImage对象了,没有必要再去重新new一个,而事实证明,就是这个new操作,导致转换后的图片出现上述问题。
根据 systemIcon.getImage()得到BufferedImage对象后,因为该对象内部数据实际上就已经是文件图标数据了,所以调用 Graphics2D绘制Icon的操作也没必要了,最后修改后的代码如下:
@Override
public  Image getImage(Object element)
{
     // 得到文件图标
    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);
    java.awt.Image image = systemIcon.getImage();
 
     int  width = image.getWidth( null );
     int  height = image.getHeight( null );
     // 得到 Icon 的数据缓冲区
    BufferedImage bufferedImage = (BufferedImage) systemIcon.getImage();
     // 读取缓冲区图片数据到一个数组
     int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
     // 将没有颜色的点设置为白色
     for  ( int  i = 0; i < data. length ; i++)
    {
     if  (data[i] == 0)
        data[i] = 0xFFFFFF;
    }
     // 根据数组数据生成 ImageData 对象
    ImageData imageData =  new  ImageData(width, height, 24,  new  PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    imageData.setPixels(0, 0, data. length , data, 0);
     // 生成 Image 对象
    Image swtImage =  new  Image(PlatformUI.getWorkbench().getDisplay(), imageData);
     return  swtImage;
}
这回效果图如下:
003
看起来好看多了,基本上跟Windows资源管理器的效果差不多了。不过如果目光依旧敏锐的话,再继续打开某一驱动器,看文件夹图标,还是有一点小小的瑕疵,有些Icon在转换过来的时候,会莫名其妙的在原来没有颜色的像素点上增加一点淡淡的颜色,不过影响已经不大了,就姑且这样吧。期待有高手能够进一步将其搞定。
好消息,这个问题我自己搞定了,参见《把Swing的Icon转换到SWT的Image(续)》这篇文档。





本文转自 tywali 51CTO博客,原文链接:http://blog.51cto.com/lancelot/331636,如需转载请自行联系原作者
目录
相关文章
|
2月前
swing/swt 支持多屏幕显示
swing/swt 支持多屏幕显示
|
Oracle 安全 Java
Java GUI框架选择什么?Swing,SWT,AWT,SwingX,JGoodies,JavaFX,Apache Pivot?
Java GUI框架选择什么?Swing,SWT,AWT,SwingX,JGoodies,JavaFX,Apache Pivot?
1019 0
|
Java
Java Swing 实现loading进度条加载效果
这个可以用来做一些页面的加载进度条还是很不错的,起到美观的作用,一些代码内容也是根据别的大佬拿来修改完成。这是在idea里面运行的
329 0
Java Swing 实现loading进度条加载效果
Java_Swing中让窗口居中显示的方法(三种方法)
Java_Swing中让窗口居中显示的方法(三种方法)
547 0
|
Java Spring
[SOLVED] Caused by: java.awt.HeadlessException when trying to create a SWING/AWT frame from Sprin...
[SOLVED] Caused by: java.awt.HeadlessException when trying to create a SWING/AWT frame from Spring Boot In Spring Boot, when y...
1255 0
pi4j,Netbeans中togglebutton跟Jbutton的区别
一组togglebutton中会始终有一个是按下去的状态 一组commandbutton就全部都始终都是弹起的状态
1277 0
|
前端开发 Android开发
在SWT里显示AWT对象
今天遇到一个问题,就是要在一个Eclipse插件里显示JFreeChart的图形,因为后者是基于Java2D的,要把图形显示在SWT应用程序里需要利用SWT-AWT桥接器来实现,虽说桥接的方式多半会伴随着性能下降,但总归是一个解决方法。
1295 0
|
Shell
SWT里Slider和Scale的区别
以前以为Slider和Scale之间只是外观的区别,今天发现不是这样的,因为Slider有一个特点:getSelection()能得到的最 大值并不是getMaximum()的值,要减去getThumb()值,后者是中间的滑块所拥有的值,缺省为10,最小为1。
1235 0