2012-06-19 5 views
5

나는 JPanel에 그림을 그리는 프로그램을 작성 중입니다. 어떻게 그 위에 그려진 JPanelImage을 얻을 수 있습니까? 이 코드를 시도했지만 배경색이 JPanel 인 빈 이미지 만 있습니다. BufferedImage에는 내 패널에 색칠 된 것이 포함되어 있지 않습니다.자바 - 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; 
    } 

내가 뭘 잘못하고 있니?

+0

것은 당신이 당신의 이미지를 그리는 방법을 게시 고려하십시오. graphics.drawImage를 사용합니까? 그렇다면 ImageObserver 인수는 무엇입니까? –

답변

2

다음은 작동하는 SSCCE입니다. 일반적인 실수는 을 drawImage 메서드의 ImageObserver 메서드로 전달하는 것입니다. 이미지 로딩이 비동기이기 때문입니다.

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

그것을 시도, 나던 작동하지 않습니다. –

+2

@sijoune 위에 게시 한 코드를 시도하고 코드와의 차이점을 확인하여 문제를 발견하십시오. –

2

코드가 작동합니다.

다음은 간단한 예입니다. 프레임 크기를 변경하여 이미지가 움직이는 지 확인하십시오.

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

따라서 문제는 다른 곳에서 발생해야합니다. 패널의 이미지를 만들 때 패널의 크기가 긍정적인지 확인하십시오.

2

다음은 Java 2/JDK 1.2 응용 프로그램에 추가 할 수있는 빠른 예제 메소드입니다. 스냅 샷하려는 구성 요소와 저장할 파일 이름을 전달하기 만하면됩니다.

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

이 방법은 매우 다양합니다. 이 도구를 사용하여 다양한 Java 응용 프로그램 구성 요소의 스냅 샷을 만들 수 있습니다. 그러나 com.sun.image.codec.jpeg를 코드의 이식성에 위험을 감수하면서 사용하는 것이 좋습니다.

편집

: 나는 확인 코드를 테스트하고 모두가 잘 보인다

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

나는 그것을 시도하고 동일한 일이 발생합니다. 나는 그것을 얻지 않는다. 나는 틀린 뭔가를하고있을 것입니다. 그러나 그것을 찾을 수 없습니다. –

+0

내 편집을 확인하고 문제를 일으킬 수있는 코드를 게시 할 수 있습니다. 코드를 게시하면 구성 요소와 파일 이름을 메서드에 전달하기 때문에 나머지는 수행 할 수 있습니다. –