我想将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的全部内容转换为图像?
答案 0 :(得分:12)
但问题是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);
}
}
<强>更新强>
根据你的评论:
我通过使用将BufferedImage写入文件 ImageIO.write(bufferedImage,“jpg”,file);这对两者都很好 png和gif图像,但jpg图像显示红色背景而不是 白色。我该如何解决这个问题呢。感谢
有关详情,请参阅this类似的问题/答案。你可以这样做:
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();
}
}
答案 1 :(得分:3)
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;
}
答案 2 :(得分:1)
我不知道为什么你需要做一些如此复杂的事情。只要您的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();
}