如何将图标转换为图像

我正在尝试使用以下代码将Icon( javax.swing.Icon )转换为Image( 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函数会在image.getGraphics()上抛出NullPointerException

对于记录, icon值是默认的CheckBox图标(通过UIManager.getIcon("CheckBox.icon")

以下是抛出exception的详细信息:

 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.(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) 

如果您需要更多详细信息,请告诉我,我将编辑我的post以添加它们。

谢谢!

刚刚找到一个代码片段,如果你想更频繁地包装那些行为不端的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 (fi 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); 

尝试这个 :

 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提供的图标,将其转换为Image并在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); } } } 

尝试这个:

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

我无法准确解释为什么它需要一个JCheckBox 。 也许这个图标有所不同? NullPointerException来自MetalIconFactory用于"CheckBox.icon"这一行:

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