2011-04-29 21 views
22

我想一個圖標(javax.swing.icon)轉換爲圖像(java.awt.Image)使用此代碼:我如何可以轉換一個圖標的圖片

private Image iconToImage(Icon icon) 
{ 
    if(icon instanceof ImageIcon) 
    { 
     return ((ImageIcon) icon).getImage(); 
    } 
    else 
    { 
     BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_RGB); 
     icon.paintIcon(null, image.getGraphics(), 0, 0); 
     return image; 
    } 
} 

的事情是,在paintIcon函數拋出我在NullPointerExceptionimage.getGraphics()

根據記錄,該icon值爲默認複選框圖標(通過UIManager.getIcon("CheckBox.icon")獲得)

這裏是異常的細節拋出:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at com.sun.java.swing.plaf.windows.WindowsIconFactory$CheckBoxIcon.paintIcon(WindowsIconFactory.java:306) 
    at utils.WarningRenderer.iconToImage(WarningRenderer.java:50) 
    at utils.WarningRenderer.<init>(WarningRenderer.java:38) 
    at deliveryexpress.DeliveryExpressView.setWarnings(DeliveryExpressView.java:278) 
    at deliveryexpress.DeliveryExpressView.updateLists(DeliveryExpressView.java:218) 
    at deliveryexpress.DeliveryExpressView.access$1100(DeliveryExpressView.java:47) 
    at deliveryexpress.DeliveryExpressView$5.addCheck(DeliveryExpressView.java:183) 
    at org.japura.gui.model.DefaultListCheckModel.fireCheckListModelListeners(Unknown Source) 
    at org.japura.gui.model.DefaultListCheckModel.fireAddCheckListModelListeners(Unknown Source) 
    at org.japura.gui.model.DefaultListCheckModel.addCheck(Unknown Source) 
    at org.japura.gui.CheckList$1.mouseClicked(Unknown Source) 
    at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:253) 
    at java.awt.Component.processMouseEvent(Component.java:6292) 
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267) 
    at java.awt.Component.processEvent(Component.java:6054) 
    at java.awt.Container.processEvent(Container.java:2041) 
    at java.awt.Component.dispatchEventImpl(Component.java:4652) 
    at java.awt.Container.dispatchEventImpl(Container.java:2099) 
    at java.awt.Component.dispatchEvent(Component.java:4482) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577) 
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4247) 
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168) 
    at java.awt.Container.dispatchEventImpl(Container.java:2085) 
    at java.awt.Window.dispatchEventImpl(Window.java:2478) 
    at java.awt.Component.dispatchEvent(Component.java:4482) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:644) 
    at java.awt.EventQueue.access$000(EventQueue.java:85) 
    at java.awt.EventQueue$1.run(EventQueue.java:603) 
    at java.awt.EventQueue$1.run(EventQueue.java:601) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) 
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98) 
    at java.awt.EventQueue$2.run(EventQueue.java:617) 
    at java.awt.EventQueue$2.run(EventQueue.java:615) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:614) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) 

如果您需要更多的細節,只是告訴我,我將編輯我的帖子以添加它們。

謝謝!

+4

完善的問題,因爲:-) – kleopatra 2011-04-29 10:17:25

回答

14

剛剛發現的代碼片段,如果你想換那些行爲不端的LAF往往提供的圖標可能幫助:

/** 
* Some ui-icons misbehave in that they unconditionally class-cast to the 
* component type they are mostly painted on. Consequently they blow up if 
* we are trying to paint them anywhere else (f.i. in a renderer). 
* 
* This Icon is an adaption of a cool trick by Darryl Burke/Rob Camick found at 
* http://tips4java.wordpress.com/2008/12/18/icon-table-cell-renderer/#comment-120 
* 
* The base idea is to instantiate a component of the type expected by the icon, 
* let it paint into the graphics of a bufferedImage and create an ImageIcon from it. 
* In subsequent calls the ImageIcon is used. 
* 
*/ 
public static class SafeIcon implements Icon { 

    private Icon wrappee; 
    private Icon standIn; 

    public SafeIcon(Icon wrappee) { 
     this.wrappee = wrappee; 
    } 

    @Override 
    public int getIconHeight() { 
     return wrappee.getIconHeight(); 
    } 

    @Override 
    public int getIconWidth() { 
     return wrappee.getIconWidth(); 
    } 

    @Override 
    public void paintIcon(Component c, Graphics g, int x, int y) { 
     if (standIn == this) { 
      paintFallback(c, g, x, y); 
     } else if (standIn != null) { 
      standIn.paintIcon(c, g, x, y); 
     } else { 
      try { 
       wrappee.paintIcon(c, g, x, y); 
      } catch (ClassCastException e) { 
       createStandIn(e, x, y); 
       standIn.paintIcon(c, g, x, y); 
      } 
     } 
    } 

    /** 
    * @param e 
    */ 
    private void createStandIn(ClassCastException e, int x, int y) { 
     try { 
      Class<?> clazz = getClass(e); 
      JComponent standInComponent = getSubstitute(clazz); 
      standIn = createImageIcon(standInComponent, x, y); 
     } catch (Exception e1) { 
      // something went wrong - fallback to this painting 
      standIn = this; 
     } 
    } 

    private Icon createImageIcon(JComponent standInComponent, int x, int y) { 
     BufferedImage image = new BufferedImage(getIconWidth(), 
       getIconHeight(), BufferedImage.TYPE_INT_ARGB); 
      Graphics g = image.createGraphics(); 
      try { 
       wrappee.paintIcon(standInComponent, g, 0, 0); 
       return new ImageIcon(image); 
      } finally { 
       g.dispose(); 
      } 
    } 

    /** 
    * @param clazz 
    * @throws IllegalAccessException 
    */ 
    private JComponent getSubstitute(Class<?> clazz) throws IllegalAccessException { 
     JComponent standInComponent; 
     try { 
      standInComponent = (JComponent) clazz.newInstance(); 
     } catch (InstantiationException e) { 
      standInComponent = new AbstractButton() { 

      }; 
      ((AbstractButton) standInComponent).setModel(new DefaultButtonModel()); 
     } 
     return standInComponent; 
    } 

    private Class<?> getClass(ClassCastException e) throws ClassNotFoundException { 
     String className = e.getMessage(); 
     className = className.substring(className.lastIndexOf(" ") + 1); 
     return Class.forName(className); 

    } 

    private void paintFallback(Component c, Graphics g, int x, int y) { 
     g.drawRect(x, y, getIconWidth(), getIconHeight()); 
     g.drawLine(x, y, x + getIconWidth(), y + getIconHeight()); 
     g.drawLine(x + getIconWidth(), y, x, y + getIconHeight()); 
    } 

} 

要使用片段中,簡單地通過在任意成分:

icon = new SafeIcon(icon); 
    BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_RGB); 
    icon.paintIcon(new JPanel(), image.getGraphics(), 0, 0); 
+1

謝謝,它工作!它不包括alpha,但我會嘗試自己解決這個問題:p – 3rgo 2011-04-29 12:17:36

+0

如何包含alpha? – oliholz 2012-01-16 11:02:11

+2

@oliholz可能缺少一些東西,但創建一個支持alpha類型的BufferedImage有什麼問題,比如TYPE_INT_ARGB? – kleopatra 2012-01-16 11:59:14

2

試試這個:

icon.paintIcon(new JCheckBox(), image.getGraphics(), 0, 0); 

我也解釋不清楚爲什麼需要一個JCheckBox雖然。也許它因圖標而異?該NullPointerException來自該行MetalIconFactory"CheckBox.icon"

ButtonModel model = ((JCheckBox)c).getModel(); 
+1

僅供參考一切必要的細節:國家相關的聖像畫是windowsCheckBoxIcon相似。這些圖標實現非常糟糕,因爲它們假定給定的組件是JCheckBox類型。根據合同,paintIcon _must_應對任意組件類型,包括根本沒有 – kleopatra 2011-04-29 10:15:36

7

試試:

static Image iconToImage(Icon icon) { 
    if (icon instanceof ImageIcon) { 
     return ((ImageIcon)icon).getImage(); 
    } 
    else { 
     int w = icon.getIconWidth(); 
     int h = icon.getIconHeight(); 
     GraphicsEnvironment ge = 
     GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice gd = ge.getDefaultScreenDevice(); 
     GraphicsConfiguration gc = gd.getDefaultConfiguration(); 
     BufferedImage image = gc.createCompatibleImage(w, h); 
     Graphics2D g = image.createGraphics(); 
     icon.paintIcon(null, g, 0, 0); 
     g.dispose(); 
     return image; 
    } 
} 

一個完整的例子,我們採用laf提供的圖標,將其轉換爲圖像並用於Windows系統托盤。

import java.awt.*; 
import java.awt.image.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class SysTrayDemo { 
    protected static TrayIcon trayIcon; 
    private static PopupMenu createTrayMenu() { 
     ActionListener exitListener = new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("Bye from the tray"); 
       System.exit(0); 
      } 
     }; 

     ActionListener executeListener = new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       JOptionPane.showMessageDialog 
        (null, "Popup from the action on the systray!", 
        "User action", JOptionPane.INFORMATION_MESSAGE); 
       trayIcon.displayMessage 
        ("Done", "You can do it again if you want!", 
        TrayIcon.MessageType.INFO); 
      } 
     }; 

     PopupMenu menu = new PopupMenu(); 
     MenuItem execItem = new MenuItem("Action..."); 
     execItem.addActionListener(executeListener); 
     menu.add(execItem); 

     MenuItem exitItem = new MenuItem("Exit"); 
     exitItem.addActionListener(exitListener); 
     menu.add(exitItem); 
     return menu; 
    } 

    /** 
    * using a built-in icon 
    * we need to convert the icon to an Image 
    */ 
    private static TrayIcon createTrayIconFromBuiltInIcon() { 
     Icon icon = UIManager.getIcon("OptionPane.warningIcon"); 
     PopupMenu popup = createTrayMenu(); 
     Image image = iconToImage(icon); 
     TrayIcon ti = new TrayIcon(image, "Java System Tray Demo", popup); 
     ti.setImageAutoSize(true); 
     return ti; 
    } 

    static Image iconToImage(Icon icon) { 
      if (icon instanceof ImageIcon) { 
       return ((ImageIcon)icon).getImage(); 
      } else { 
       int w = icon.getIconWidth(); 
       int h = icon.getIconHeight(); 
       GraphicsEnvironment ge = 
       GraphicsEnvironment.getLocalGraphicsEnvironment(); 
       GraphicsDevice gd = ge.getDefaultScreenDevice(); 
       GraphicsConfiguration gc = gd.getDefaultConfiguration(); 
       BufferedImage image = gc.createCompatibleImage(w, h); 
       Graphics2D g = image.createGraphics(); 
       icon.paintIcon(null, g, 0, 0); 
       g.dispose(); 
       return image; 
      } 
     } 

    public static void main(String[] args) throws Exception { 
     if (!SystemTray.isSupported()) { 
      System.out.println 
       ("System tray not supported on this platform"); 
      System.exit(1); 
     } 

     try { 
      SystemTray sysTray = SystemTray.getSystemTray(); 
      trayIcon = createTrayIconFromBuiltInIcon(); 
      sysTray.add(trayIcon); 
      trayIcon.displayMessage("Ready", 
       "Tray icon started and tready", TrayIcon.MessageType.INFO); 
     } 
     catch (AWTException e) { 
      System.out.println("Unable to add icon to the system tray"); 
      System.exit(1); 
     } 
    } 
} 
+1

已經在一小時前評論過,再次做:你認爲這將有助於異常的原因,那就是laf提供的圖標不能應付零組件? ......這個錯誤的答案是怎麼回來的? – kleopatra 2011-04-29 11:57:07

+0

@kleopatra,也許是因爲它的工作正常,如我的測試案例所示。 – RealHowTo 2011-04-29 15:10:18

+1

所以你很幸運的OptionPane.warningIcon ;-)嘗試與checkbox.icon(metal-/windowsLAF),這是要解決的問題相同... – kleopatra 2011-04-29 15:26:43

相關問題