2012-06-19 149 views
5

Estoy escribiendo un programa en el que pinto en un JPanel. ¿Cómo obtengo un Image del JPanel que está pintado? He intentado este código pero todo lo que obtengo es una imagen en blanco con el color de fondo de mi JPanel. El BufferedImage no contiene lo que está pintado en mi panel.Java - Obtener una imagen de un JPanel

private BufferedImage createImage(JPanel panel) {  
     int w = panel.getWidth(); 
     int h = panel.getHeight(); 
     BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
     Graphics2D g = bi.createGraphics(); 
     panel.paint(g); 
     return bi; 
    } 

¿Qué estoy haciendo mal?

+0

Considerar la publicación de cómo se dibuja la imagen. ¿Usas graphics.drawImage? En caso afirmativo, ¿cuál es el argumento de ImageObserver? –

Respuesta

2

Aquí hay un SSCCE que ilustra que funciona. Un error común es pasar null como ImageObserver del método drawImage, porque la carga de la imagen es asincrónica.

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.net.MalformedURLException; 
import java.net.URL; 

import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class TestPrint { 

    protected static void initUI() throws MalformedURLException { 
     final ImageIcon image = new ImageIcon(new URL("http://www.travelblog.org/Wallpaper/pix/tb_fiji_sunset_wallpaper.jpg")); 
     JPanel panel = new JPanel() { 
      @Override 
      protected void paintComponent(java.awt.Graphics g) { 
       super.paintComponent(g); 
       g.drawImage(image.getImage(), 0, 0, this); 
      }; 
     }; 
     panel.setPreferredSize(new Dimension(image.getIconWidth(), image.getIconHeight())); 
     panel.setSize(panel.getPreferredSize()); 
     BufferedImage bi = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_RGB); 
     Graphics g = bi.createGraphics(); 
     panel.print(g); 
     g.dispose(); 
     try { 
      ImageIO.write(bi, "png", new File("test.png")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       try { 
        initUI(); 
       } catch (MalformedURLException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 
} 
+0

lo probé, no funciona. –

+2

@sijoune Pruebe el código que publiqué arriba y vea las diferencias con su código para detectar su problema. –

2

Tu código funciona para mí.

Aquí hay un ejemplo simple. Cambie el tamaño del marco para ver el tamaño de cambio del panel y la imagen moverse.

public static void main(String[] args) { 
    JFrame frame = new JFrame("Test"); 
    JPanel panel = new JPanel(); 
    panel.setBackground(Color.BLUE); 
    JLabel label = new JLabel("Image"); 
    label.setForeground(Color.RED); 
    panel.add(label); 
    frame.add(panel, BorderLayout.NORTH); 
    frame.pack(); 
    JLabel image = new JLabel(new ImageIcon(createImage(panel))); 
    frame.add(image, BorderLayout.SOUTH); 
    frame.pack(); 
    label.setText("Original");  
    frame.setVisible(true); 
} 

private static BufferedImage createImage(JPanel panel) { 
    int w = panel.getWidth(); 
    int h = panel.getHeight(); 
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
    Graphics2D g = bi.createGraphics(); 
    panel.paint(g); 
    return bi; 
} 

Entonces, su problema debe ser otro. Asegúrese de que su panel tenga un tamaño positivo en el punto en que cree una imagen del mismo.

2

Aquí hay un método de ejemplo rápido que puede agregar a cualquiera de sus aplicaciones Java 2/JDK 1.2. Simplemente ingrese el componente que desea capturar y el nombre de archivo en el que desea guardar.

public void saveComponentAsJPEG(Component myComponent, String filename) { 
    Dimension size = myComponent.getSize(); 
    BufferedImage myImage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); 
    Graphics2D g2 = myImage.createGraphics(); 
    myComponent.paint(g2); 
    try { 
     OutputStream out = new FileOutputStream(filename); 
     JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
     encoder.encode(myImage); 
     out.close(); 
    } catch (Exception e) { 
     System.out.println(e); 
    } 
} 

Este método es muy versátil. Se puede usar para tomar instantáneas de una amplia variedad de componentes de aplicaciones Java. Tenga en cuenta, sin embargo, que utiliza com.sun.image.codec.jpeg con algún riesgo para la portabilidad de su código.

EDIT: He probado el código para asegurarse y todo parece estar bien:

import com.sun.image.codec.jpeg.JPEGCodec; 
import com.sun.image.codec.jpeg.JPEGImageEncoder; 
import java.awt.*; 
import java.awt.geom.Ellipse2D; 
import java.awt.image.BufferedImage; 
import java.io.FileOutputStream; 
import java.io.OutputStream; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class ScreenCapture extends JFrame { 

    public ScreenCapture() { 
     createAndShowUI(); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       ScreenCapture screenCapture = new ScreenCapture(); 
      } 
     }); 
    } 

    private void createAndShowUI() { 
     setTitle("Test Screen Capture"); 
     setSize(300, 300); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLocationRelativeTo(null); 
     getContentPane().add(new DrawingPanel()); 
     setVisible(true); 
     saveComponentAsJPEG(this, "C:/test.jpg"); 

    } 

    public void saveComponentAsJPEG(Component myComponent, String filename) { 
     Dimension size = myComponent.getSize(); 
     BufferedImage myImage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); 
     Graphics2D g2 = myImage.createGraphics(); 
     myComponent.paint(g2); 
     try { 
      OutputStream out = new FileOutputStream(filename); 
      JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
      encoder.encode(myImage); 
      out.close(); 
     } catch (Exception e) { 
      System.out.println(e); 
     } 
    } 

    class DrawingPanel extends JPanel { 

     public DrawingPanel() { 
      setDoubleBuffered(true); 
     } 

     @Override 
     public void paintComponent(Graphics grphcs) { 
      super.paintComponents(grphcs); 
      Graphics2D g2d = (Graphics2D) grphcs; 

      RenderingHints rhints = g2d.getRenderingHints(); 
      boolean antialiasOn = rhints.containsValue(RenderingHints.VALUE_ANTIALIAS_ON); 

      if (!antialiasOn) { 
       g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
      } 

      Shape circle = new Ellipse2D.Float(100.0f, 100.0f, 100.0f, 100.0f); 

      g2d.setColor(Color.RED); 
      g2d.draw(circle); 
      g2d.fill(circle); 
     } 
    } 
} 
+0

Lo probé y sucede lo mismo. No lo entiendo Debo estar haciendo algo mal, pero no puedo encontrarlo. –

+0

reviso mi edición, y tal vez luego publique el código que podría estar dando problemas, pero no veo cómo, porque como puede ver una vez que pasa un componente y nombre de archivo al método, hace el resto. –

Cuestiones relacionadas