天天看點

把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

<b>public</b> Image getImage(Object element)

{

    //得到檔案圖示

    ImageIcon systemIcon = (ImageIcon) FileSystemView.getFileSystemView().getSystemIcon((File) element);

    java.awt.Image image = systemIcon.getImage();

    <b>int</b> width = image.getWidth(<b>null</b>);

    <b>int</b> height = image.getHeight(<b>null</b>);

    //建立用于繪制Icon的緩沖區

    BufferedImage bufferedImage = <b>new</b> BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

    //繪制Icon到緩沖區

    Graphics2D g2d = bufferedImage.createGraphics();

    g2d.drawImage(image, 0, 0, <b>null</b>);

    g2d.dispose();

    //讀取緩沖區圖檔資料到一個數組

    <b>int</b>[] data = ((DataBufferInt) bufferedImage.getData().getDataBuffer()).getData();

    //根據數組資料生成ImageData對象

    ImageData imageData = <b>new</b> ImageData(width, height, 24, <b>new</b> PaletteData(0xFF0000, 0x00FF00, 0x0000FF));

    imageData.setPixels(0, 0, data.length, data, 0);

    //生成Image對象

    Image swtImage = <b>new</b> Image(PlatformUI.getWorkbench().getDisplay(), imageData);

    <b>return</b> swtImage;

}

Icon的确是轉換到Image了,看下面的效果圖:

<a href="http://lancelot.blog.51cto.com/attachment/201006/13/393579_12763975514X8E.jpg"></a>

雖然Icon轉換到了Image,可是圖檔周圍全都是黑色,這是因為Icon在轉換的時候,原來的圖檔裡面是透明色的像素點,轉換過來系統自動變成了黑色,是以代碼還需要額外的處理一下,修改後的代碼如下:

    //将沒有顔色的點設定為白色

    <b>for</b> (<b>int</b> i = 0; i &amp;lt; data.length; i++)

    {

    <b>if</b> (data[i] == 0)

        data[i] = 0xFFFFFF;

    }

和上面的代碼相比,新增加了一個循環,将緩沖區内為0的資料修改為0xFFFFFF,也就是将相應的像素設定為白色,效果圖如下:

<a href="http://lancelot.blog.51cto.com/attachment/201006/13/393579_1276397553bu8y.jpg"></a>

看起來效果好多了,可是如果目光敏銳一點的話,還是能夠看出破綻來,截取一個圖示,放大後仔細看一看:

<a href="http://lancelot.blog.51cto.com/attachment/201006/13/393579_12763975540eYR.png"></a>

和正常的圖示對比一下,可以發現邊邊角角的顔色都不對,普遍偏深,可是網上找到的資料到這裡就為止了,沒有人提出來如何解決這個問題,當然,這也可能跟我的系統有關系。經過跟蹤和調試,發現其實調用systemIcon.getImage() 得到的對象就已經是一個BufferedImage對象了,沒有必要再去重新new一個,而事實證明,就是這個new操作,導緻轉換後的圖檔出現上述問題。

根據systemIcon.getImage()得到BufferedImage對象後,因為該對象内部資料實際上就已經是檔案圖示資料了,是以調用Graphics2D繪制Icon的操作也沒必要了,最後修改後的代碼如下:

    //得到Icon的資料緩沖區

    BufferedImage bufferedImage = (BufferedImage) systemIcon.getImage();

這回效果圖如下:

<a href="http://lancelot.blog.51cto.com/attachment/201006/13/393579_1276397556snvs.jpg"></a>

看起來好看多了,基本上跟Windows資料總管的效果差不多了。不過如果目光依舊敏銳的話,再繼續打開某一驅動器,看檔案夾圖示,還是有一點小小的瑕疵,有些Icon在轉換過來的時候,會莫名其妙的在原來沒有顔色的像素點上增加一點淡淡的顔色,不過影響已經不大了,就姑且這樣吧。期待有高手能夠進一步将其搞定。

本文轉自 tywali 51CTO部落格,原文連結:http://blog.51cto.com/lancelot/331636,如需轉載請自行聯系原作者