把Swing的Icon转换到SWT的Image

环境:Windows七、Eclipse 3.五、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 p_w_picpath = systemIcon.getImage();
 
    int width = p_w_picpath.getWidth( null );
    int height = p_w_picpath.getHeight( null );
    // 建立用于绘制 Icon 的缓冲区
    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage. TYPE_INT_RGB );
 
    // 绘制 Icon 到缓冲区
    Graphics2D g2d = bufferedImage.createGraphics();
    g2d.drawImage(p_w_picpath, 0, 0, null );
    g2d.dispose();
    // 读取缓冲区图片数据到一个数组
    int [] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();
    // 根据数组数据生成 ImageData 对象
    ImageData p_w_picpathData = new ImageData(width, height, 24, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    p_w_picpathData.setPixels(0, 0, data. length , data, 0);
    // 生成 Image 对象
    Image swtImage = new Image(PlatformUI.getWorkbench().getDisplay(), p_w_picpathData);
    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 p_w_picpath = systemIcon.getImage();
 
    int width = p_w_picpath.getWidth( null );
    int height = p_w_picpath.getHeight( null );
    // 建立用于绘制 Icon 的缓冲区
    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage. TYPE_INT_RGB );
 
    // 绘制 Icon 到缓冲区
    Graphics2D g2d = bufferedImage.createGraphics();
    g2d.drawImage(p_w_picpath, 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 p_w_picpathData = new ImageData(width, height, 24, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    p_w_picpathData.setPixels(0, 0, data. length , data, 0);
    // 生成 Image 对象
    Image swtImage = new Image(PlatformUI.getWorkbench().getDisplay(), p_w_picpathData);
    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 p_w_picpath = systemIcon.getImage();
 
    int width = p_w_picpath.getWidth( null );
    int height = p_w_picpath.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 p_w_picpathData = new ImageData(width, height, 24, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
    p_w_picpathData.setPixels(0, 0, data. length , data, 0);
    // 生成 Image 对象
    Image swtImage = new Image(PlatformUI.getWorkbench().getDisplay(), p_w_picpathData);
    return swtImage;
}
这回效果图以下:
003
看起来好看多了,基本上跟Windows资源管理器的效果差很少了。不过若是目光依旧敏锐的话,再继续打开某一驱动器,看文件夹图标,仍是有一点小小的瑕疵,有些Icon在转换过来的时候,会莫名其妙的在原来没有颜色的像素点上增长一点淡淡的颜色,不过影响已经不大了,就姑且这样吧。期待有高手可以进一步将其搞定。
好消息,这个问题我本身搞定了,参见《把Swing的Icon转换到SWT的Image(续)》这篇文档。
相关文章
相关标签/搜索