将JPanel转换为JScrollPane中的图像

我想将JPanel转换为图像。 我使用以下方法:

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

但问题是JPanel包含在JScrollPane中。 因此,当我将jpanel转换为图像时,图像仅包含jpanel中可见的部分,并且隐藏在滚动窗格内部的部分不包含在图像中。

是否有任何解决方案可以将JPanel的全部内容转换为图像?

但问题是JPanel包含在JScrollPane中。 因此,当我将jpanel转换为图像时,图像仅包含jpanel中可见的部分,并且隐藏在滚动窗格内部的部分不包含在图像中。

这不会发生在我身上……你尝试过paintAll而不是paint吗?

这是一个很好的方法,可以捕获任何可见或不可见的Component的内容(它不是我的,我把它从SO的某个地方得到它并从那以后使用它):

 public static BufferedImage componentToImage(Component component, boolean visible) { if (visible) { BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT); Graphics2D g2d = (Graphics2D) img.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); component.paintAll(g2d); return img; } else { component.setSize(component.getPreferredSize()); layoutComponent(component); BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT); CellRendererPane crp = new CellRendererPane(); crp.add(component); crp.paintComponent(img.createGraphics(), component, crp, component.getBounds()); return img; } } private static void layoutComponent(Component c) { synchronized (c.getTreeLock()) { c.doLayout(); if (c instanceof Container) { for (Component child : ((Container) c).getComponents()) { layoutComponent(child); } } } } 

以下是展示上述内容的示例:

框架视图:

在此处输入图像描述

捕获小组:

在此处输入图像描述

 import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.CellRendererPane; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; public class Test { public Test() { createAndShowGui(); } private void createAndShowGui() { JFrame frame = new JFrame() { @Override public Dimension getPreferredSize() {//size frame purposefully smaller return new Dimension(100, 100); } }; frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); Image img = null; try { img = ImageIO.read(new URL("http://images4.wikia.nocookie.net/__cb20120515073660/naruto/images/0/09/Naruto_newshot.png")).getScaledInstance(200, 200, Image.SCALE_SMOOTH); } catch (Exception ex) { ex.printStackTrace(); } final ImagePanel imagePanel = new ImagePanel(200, 200, img); JScrollPane jsp = new JScrollPane(imagePanel); frame.add(jsp); frame.pack(); frame.setVisible(true); BufferedImage bi = componentToImage(imagePanel, true); try { File outputfile = new File("c:/saved.png"); ImageIO.write(bi, "png", outputfile); } catch (IOException e) { e.printStackTrace(); } } public static BufferedImage componentToImage(Component component, boolean visible) { if (visible) { BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT); Graphics2D g2d = (Graphics2D) img.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); component.paintAll(g2d); return img; } else { component.setSize(component.getPreferredSize()); layoutComponent(component); BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT); CellRendererPane crp = new CellRendererPane(); crp.add(component); crp.paintComponent(img.createGraphics(), component, crp, component.getBounds()); return img; } } private static void layoutComponent(Component c) { synchronized (c.getTreeLock()) { c.doLayout(); if (c instanceof Container) { for (Component child : ((Container) c).getComponents()) { layoutComponent(child); } } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Test(); } }); } } class ImagePanel extends JPanel { int width, height; Image bg; public ImagePanel(int width, int height, Image bg) { this.width = width; this.height = height; this.bg = bg; } @Override public Dimension getPreferredSize() { return new Dimension(width, height); } @Override protected void paintComponent(Graphics grphcs) { super.paintComponent(grphcs); grphcs.drawImage(bg, 0, 0, null); } } 

更新:

根据你的评论:

我使用ImageIO.write(bufferedImage,“jpg”,file)将BufferedImage写入文件; 这适用于png和gif图像,但jpg图像显示红色背景而不是白色。 我该如何解决这个问题呢。 谢谢

有关更多信息,请参阅此类似问题/答案 你会做的事情如下:

 private static final int[] RGB_MASKS = {0xFF0000, 0xFF00, 0xFF}; private static final ColorModel RGB_OPAQUE = new DirectColorModel(32, RGB_MASKS[0], RGB_MASKS[1], RGB_MASKS[2]); ... BufferedImage image = componentToImage(imagePanel, true); saveJPeg(image, "c:/saved.jpg"); private void saveJPeg(BufferedImage image, String name) { PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, true); try { pg.grabPixels(); } catch (InterruptedException ex) { ex.printStackTrace(); } int width = pg.getWidth(), height = pg.getHeight(); DataBuffer buffer = new DataBufferInt((int[]) pg.getPixels(), pg.getWidth() * pg.getHeight()); WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, RGB_MASKS, null); BufferedImage bi = new BufferedImage(RGB_OPAQUE, raster, false, null); try { ImageIO.write(bi, "jpg", new File(name)); } catch (IOException ex) { ex.printStackTrace(); } } 

SwingUtilities.paintComponent做到了:

 static void drawComponent(JComponent c, BufferedImage destination) { JFrame frame = new JFrame(); Graphics g = destination.createGraphics(); SwingUtilities.paintComponent(g, c, frame.getContentPane(), 0, 0, destination.getWidth(), destination.getHeight()); g.dispose(); frame.dispose(); } static BufferedImage createSnapshotOf(JComponent c) { Dimension size = c.getSize(); if (size.width <= 0 || size.height <= 0) { size = c.getPreferredSize(); } BufferedImage snapshot = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); drawComponent(c, snapshot); return snapshot; } 

我不知道为什么你需要做那么复杂的事情。 只要您的Buffered图像和绘制函数都使用JScroolPane中的组件(巨大),就应该保存整个内容。

  //create a tree data structure DefaultMutableTreeNode tree = new DefaultMutableTreeNode("root"); //optional: you can make the tree really big //now show the tree JFrame frame = new JFrame("TreeDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create a Jtree component to display your data structure JTree treeDisplay = new JTree(tree); //expand the tree all out for(int i = 0; i < treeDisplay.getRowCount(); i++) { treeDisplay.expandRow(i); } //put your tree display component in a scroll pane frame.add(new JScrollPane(treeDisplay)); //Display the window. frame.pack(); frame.setVisible(true); //save tree in the window to a file BufferedImage img = new BufferedImage(treeDisplay.getWidth(), treeDisplay.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); //put graphics on the buffered image treeDisplay.paintAll(graphics); graphics.dispose(); try { ImageIO.write(img, "png", new File("tree.png")); } catch (IOException e) { e.printStackTrace(); }