web-dev-qa-db-fra.com

Comment puis-je convertir une icône en image

J'essaie de convertir une icône (javax.swing.Icon) En une image (Java.awt.Image) En utilisant ce code:

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;
    }
}

Le fait est que la fonction paintIcon lance un NullPointerException sur la image.getGraphics().

Pour mémoire, la valeur icon est l'icône CheckBox par défaut (obtenue via UIManager.getIcon("CheckBox.icon"))

Voici les détails de l'exception levée:

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)

Si vous avez besoin de plus de détails, dites-le moi, je vais modifier mon message pour les ajouter.

Merci!

22
3rgo

Je viens de trouver un extrait de code qui pourrait vous aider si vous souhaitez envelopper plus souvent les icônes mal fournies par 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());
    }

}

Pour l'utiliser dans votre extrait, passez simplement un composant arbitraire:

    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

Essaye ça :

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;
   }
 }

Un exemple complet où nous prenons une icône fournie par laf, la convertissons en une image et l'utilisons pour dans la barre d'état système de 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

Essaye ça:

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

Je ne peux pas expliquer exactement pourquoi il a besoin d'un JCheckBox cependant. Peut-être que cela varie pour l'icône? NullPointerException provenait de cette ligne dans MetalIconFactory pour "CheckBox.icon":

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