将 JPanel 保存为图像

Posted

技术标签:

【中文标题】将 JPanel 保存为图像【英文标题】:Saving JPanel as image 【发布时间】:2011-10-25 12:40:37 【问题描述】:

我正在开发一个应用程序,允许用户在图层中加载图像。用户可以在另一层上绘制一些图片并仅保存用户绘制的图像。这是我的代码:

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

public class LayerDemo extends JApplet 

    private JLayeredPane mainLayer;

    private JPanel layer1;

    private JPanel layer2;

    private JLabel label;

    private ImageIcon imgIcon;


    /**
     * Create the applet.
     */
    public LayerDemo()     
    

    public void init() 
        Dimension mainDemension = new Dimension(1024,768);
        setSize(mainDemension);

        mainLayer = new JLayeredPane();   
        layer1 = new JPanel();
        layer1.setOpaque(false);
        layer1.setBounds(0, 0, this.getWidth(), this.getHeight());
        imgIcon = new ImageIcon("bear.jpg");
        label = new JLabel(imgIcon);
        label.setBounds(0, 0, imgIcon.getIconWidth(), imgIcon.getIconHeight());
        layer1.add(label);

        layer2 = new PaintDemo(true);
        layer2.setOpaque(false);
        layer2.setBounds(0, 0, this.getWidth(), this.getHeight());

        mainLayer.add(layer1, 1);
        mainLayer.add(layer2, 2);
        this.setContentPane(mainLayer);
    

    public void paint(Graphics g)     
    


这是用户绘制的类:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelListener;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class PaintDemo extends JPanel 
    /**
     * field explanation
     */
    private Point startPoint = new Point();

    private Point endPoint = new Point();

    private Graphics2D g2;

    private int minX;

    private int minY;

    private int maxX;

    private int maxY;

    private int height;

    private int width;


    /**
     * Create the panel.
     */

    public PaintDemo(boolean isDoubleBuffer) 

        addMouseWheelListener(new MouseWheelListener() 
            public void mouseWheelMoved(MouseWheelEvent e) 
            
        );
        this.setDoubleBuffered(isDoubleBuffer);
        addMouseMotionListener(new MouseMotionAdapter() 
            @Override
            public void mouseDragged(MouseEvent e) 
                endPoint = e.getPoint();
                Graphics g = PaintDemo.this.getGraphics();
                paintComponent(g);
                minX = minX < endPoint.x ? minX : endPoint.x;
                minY = minY < endPoint.y ? minY : endPoint.y;
                maxX = maxX > endPoint.x ? maxX : endPoint.x;
                maxY = maxY > endPoint.y ? maxY : endPoint.y;
                startPoint = endPoint;
            
        );
        addMouseListener(new MouseAdapter() 
            @Override
            public void mousePressed(MouseEvent e) 
                startPoint = e.getPoint();
                minX = startPoint.x;
                minY = startPoint.y;
                maxX = startPoint.x;
                maxY = startPoint.y;
            

            @Override
            public void mouseReleased(MouseEvent e) 
                endPoint = e.getPoint();
                Graphics g = PaintDemo.this.getGraphics();
                paintComponent(g);
                minX = minX < endPoint.x ? minX : endPoint.x;
                minY = minY < endPoint.y ? minY : endPoint.y;
                maxX = maxX > endPoint.x ? maxX : endPoint.x;
                maxY = maxY > endPoint.y ? maxY : endPoint.y;
                minX = minX > 0 ? minX : 0;
                minY = minY > 0 ? minY : 0;
                maxX = maxX < 1024 ? maxX : 1024;
                maxY = maxY < 768 ? maxY : 768;
                width = maxX - minX;
                height = maxY - minY;
                saveImage();     
                startPoint = new Point();
                endPoint = new Point();

            
        );
    

    /**
     * Paint method
     * 
     * @inheritDoc
     */
    @Override
    public void paintComponent(Graphics g) 
        g2 = (Graphics2D)g;
        g2.setStroke(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.setFont(new Font("Serif", Font.BOLD, 18));
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.red);
        g2.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
    

    public void saveImage() 
        BufferedImage bi = new BufferedImage(PaintDemo.this.getWidth(), PaintDemo.this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = bi.createGraphics();
        paintComponent(g2);
        g2.dispose();
        try
        
            ImageIO.write(bi, "jpg", new File("clip.jpg"));
        
        catch(IOException ioe)
        
            System.out.println("Clip write help: " + ioe.getMessage());
        
    

保存图像时,它只是空白图像。请帮助我。非常感谢。 P/S:我已经按照您的想法编辑了我的代码,但它不起作用。结果是没有图像背景,仍然保存空白图像。 :(

【问题讨论】:

【参考方案1】:

自定义绘画是通过覆盖面板的paintComponent() 方法来完成的。然后使用 Graphics 对象进行绘画。

你不应该有一个空的paint()方法。

drawline() 方法不应使用 getGraphics() 方法。相反,应该将代码移至 paintComponent() 方法,然后使用传递给该方法的 Graphics 对象。

另外,您不应该覆盖小程序的paint() 方法。由于您的代码以实际大小绘制图像,因此您应该只使用 JLabel 通过创建 ImageIcon 来显示图像。然后将标签添加到分层窗格中以用作背景图像。

编辑:

为什么你还有空的paint()方法?去掉它就不需要重写paint()方法了。

当我运行代码时,我得到一个安全异常,因为小程序无法写入文件,所以我无法测试代码的那部分。但如果您有兴趣,我会使用Screen Image 来创建组件的图像。

但是,您的主要问题是绘画代码错误。是的,您会看到绘制的线条,但它们不是永久性的。当您想要进行永久绘制时,您永远不应该使用组件的 getGraphics() 方法。试着画一些线,然后最小化小程序,然后恢复小程序,你就会明白我的意思了。

解决方案是在 BufferedImage 上进行绘图。请参阅 Custom Painting Approaches 中的 DrawOnImage 示例。

【讨论】:

【参考方案2】:

请参阅ComponentImageCapture.java 以获取提示。

【讨论】:

非常感谢。我已经解决了。

以上是关于将 JPanel 保存为图像的主要内容,如果未能解决你的问题,请参考以下文章

在 JFrame 中将图像绘制到 JPanel

将图像设置为 JPanel 背景的最简单方法

将 JPanel 转换为图像

如何将图像添加到 JPanel [重复]

如何在JFrame上显示带有图像的两个JPanel,并且两个img都可见?

Java:保持JPanel背景图像的纵横比