简体   繁体   English

将 JPanel 保存为图像

[英]Saving JPanel as image

I am developing an application allow user load an image in a layer.我正在开发一个应用程序,允许用户在图层中加载图像。 User can draw some picture on another layer and save only the image that user drawn.Here is my code:用户可以在另一层上绘制一些图片并仅保存用户绘制的图像。这是我的代码:

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

}

This is the class for user draw:这是用于用户绘制的 class:

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

When save the image, it just blank image.Please help me.Thank you so much.保存图像时,它只是空白图像。请帮助我。非常感谢。 P/S: I have edited my code as your idea but it is not work. P/S:我已经按照您的想法编辑了我的代码,但它不起作用。 The result is no image background and still save blank image.结果是没有图像背景,仍然保存空白图像。 :( :(

Custom painting is done by overriding the paintComponent() method of the panel.自定义绘画是通过覆盖面板的paintComponent() 方法来完成的。 Then you use the Graphics object to do you painting.然后你用图形 object 来做你的画。

You should NOT have an empty paint() method.你不应该有一个空的 paint() 方法。

The drawline() method shouuld not use the getGraphics() method. drawline() 方法不应使用 getGraphics() 方法。 Instead that code should be moved to the paintComponent() method and then use the Graphics object passed to the method.相反,应该将代码移至 paintComponent() 方法,然后使用传递给该方法的 Graphics object。

Also, you should NOT be overriding the paint() method of the applet.此外,您不应该覆盖小程序的paint() 方法。 Since your code is painting the image at its actual size you should just use a JLabel to display the image by creating an ImageIcon.由于您的代码以实际大小绘制图像,因此您应该只使用 JLabel 通过创建 ImageIcon 来显示图像。 Then you add the label to the layered pane to use as your background image.然后将 label 添加到分层窗格中以用作背景图像。

Edit:编辑:

Why do you still have the empty paint() method?为什么你还有空的 paint() 方法? Get rid of it there is no need to override the paint() method.摆脱它,无需重写 paint() 方法。

When I run the code I get a security exception since applets are not able to write to a file so I can't test that part of your code.当我运行代码时,我得到一个安全异常,因为小程序无法写入文件,所以我无法测试代码的那部分。 But in case you are interested I use Screen Image to create images of a component.但如果您有兴趣,我会使用Screen Image来创建组件的图像。

However, you main problem is that the painting code is wrong.但是,您的主要问题是绘画代码错误。 Yes you will see lines drawn, but they are not permanent.是的,您会看到绘制的线条,但它们不是永久性的。 You should never use the getGraphics() method of a component when you want to do permanent paintinting.当您想要进行永久绘制时,您永远不应该使用组件的 getGraphics() 方法。 Try drawing some lines, then minimize the applete and then restore the applet and you will see what I mean.试着画一些线,然后最小化小程序,然后恢复小程序,你就会明白我的意思了。

The solution for this is to do your drawing on a BufferedImage.解决方案是在 BufferedImage 上进行绘图。 See the DrawOnImage example from Custom Painting Approaches .请参阅自定义绘画方法中的DrawOnImage示例。

See ComponentImageCapture.java for tips.有关提示,请参阅ComponentImageCapture.java

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM