转换一个JPanel到的图像在JScrollPane(Convert a JPanel to an

2019-07-18 19:29发布

我想要一个的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的全部内容到一个图像?

Answer 1:

但问题是,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”,文件); 这工作正常两种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();
    }
}


Answer 2:

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


Answer 3:

我不知道为什么你需要做的事情那么复杂。 只要你的缓冲图像和油漆的功能都使用的是在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();
    }


文章来源: Convert a JPanel to an image in a JScrollPane