2012-06-19 10 views
5

Piszę program, w którym maluję na JPanel. Jak mogę uzyskać obraz Image z JPanel, który jest na nim malowany? Próbowałem tego kodu, ale wszystko, co dostaję, to pusty obraz z kolorem tła mojego JPanel. Numer BufferedImage nie zawiera elementów malowanych na moim panelu.Java - Pobierz obraz 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; 
    } 

Co robię źle?

+0

Rozważmy delegowania jak narysować obraz. Czy używasz graphics.drawImage? Jeśli tak, jaki jest argument ImageObserver? –

Odpowiedz

2

Oto SSCCE ilustrujące, że działa. Typowym błędem jest podanie null jako metody ImageObserver metody, ponieważ ładowanie obrazu jest asynchroniczne.

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

próbowałem, nie działa. –

+2

@sijoune Wypróbuj kod, który napisałem powyżej i zobacz różnice w kodzie, aby wykryć problem. –

2

Twój kod działa dla mnie.

Oto prosty przykład. Zmień rozmiar ramki, aby zobaczyć rozmiar zmiany panelu i poruszanie się obrazu.

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

Twój problem musi być gdzie indziej. Upewnij się, że panel ma dodatni rozmiar w punkcie, w którym tworzysz jego obraz.

2

Oto szybka metoda przykładowa, którą można dodać do dowolnej aplikacji Java 2/JDK 1.2. Po prostu przeprowadź komponent, który chcesz migać, i nazwę pliku, który chcesz zapisać.

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

Ta metoda jest bardzo uniwersalna. Można go używać do robienia zdjęć z wielu różnych składników aplikacji Java. Należy jednak uprzedzić, że używasz pliku com.sun.image.codec.jpeg z pewnym ryzykiem przeniesienia kodu.

EDIT: Przetestowałem kod, aby upewnić się, i wszystko wydaje się w porządku:

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

Próbowałem i to samo się dzieje. Nie rozumiem tego. Muszę robić coś złego, ale nie mogę tego znaleźć. –

+0

sprawdź moją edycję, a może potem opublikuj kod, który może dawać problemy, nie widzę jak, ponieważ jak widzisz, po przejściu komponentu i nazwy pliku do metody robi on resztę? –