web-dev-qa-db-ja.com

アイコンを画像に変換する方法

次のコードを使用して、アイコン(_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関数がimage.getGraphics()NullPointerExceptionをスローすることです。

レコードの場合、icon値はデフォルトのCheckBoxアイコンです(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)
_

詳細が必要な場合はお知らせください。投稿を編集して追加します。

ありがとう!

22
3rgo

不正な動作をする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);
15
kleopatra

これを試して :

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);
        }
    }
}
8
RealHowTo

これを試して:

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

ただし、JCheckBoxが必要な理由を正確に説明することはできません。おそらくアイコンによって異なりますか? NullPointerExceptionは、"CheckBox.icon"MetalIconFactoryのこの行からのものです。

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