Java 绘制后从 JPanel 保存图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19621105/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 18:52:17  来源:igfitidea点击:

Save image from JPanel after draw

javaswingbufferedimage

提问by ??ng Nguy?n

I'm newbie in jave, my first project is draw, and save a image from JPanel, my draw is done, but I cant save it after I draw in JPanel :(, So can you help me to fix it when I open the image after draw, It doesn't contain anything :( here my codes:

我是 jave 新手,我的第一个项目是绘制,并从 JPanel 中保存图像,我的绘制完成了,但是在 JPanel 中绘制后我无法保存它:(,所以当我打开绘制后的图像,它不包含任何内容:(这里是我的代码:

package image;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class paint extends JFrame{
private Point points[] = new Point[10000];
private Point pointends[] = new Point[10000];
private int pointCount = 0;
private JButton save_btn;
public paint()
{
    panel paint2 = new panel();
    add(paint2,BorderLayout.CENTER);
}
private class panel extends JPanel
{   
    private paint my_paint;
    public panel()
    {   
        setBackground(Color.WHITE);
        save_btn = new JButton();
        save_btn.setText("123");
        this.add(save_btn);
        ButtonHandler handler1 = new ButtonHandler();
        save_btn.addActionListener(handler1);
        MouseHandler handler = new MouseHandler();
        this.addMouseMotionListener(handler);

        this.addMouseListener(handler);
    }
    private class ButtonHandler implements ActionListener
    {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            savefile();
        }

    }
    @Override
    protected void paintComponent(Graphics g) 
    {
        // TODO Auto-generated method stub
        super.paintComponent(g);
        for(int i = 0;i <pointCount;i++)
        {   
            g.setColor(Color.RED);
            g.drawLine(points[i].x, points[i].y, pointends[i].x, pointends[i].y);
        }           
    }



private class MouseHandler extends MouseAdapter
{  
    @Override
    public void mouseDragged(MouseEvent e) 
    {
        // TODO Auto-generated method stub
            pointends[ pointCount-1] = e.getPoint();
            repaint();


    }
    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
        super.mousePressed(e);
        if(pointCount < points.length)
        {
            points[ pointCount ] = e.getPoint();
            pointends[ pointCount ] = e.getPoint();
            pointCount++; 
            repaint();
        }
    }
    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
        super.mouseReleased(e);
        /*pointends[pointCount]=e.getPoint();
        repaint();
        pointCount++;
    */
    }

    }

}
public void savefile()
{
    BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT,     BufferedImage.TYPE_INT_RGB);
    JFileChooser jFile = new JFileChooser();
    jFile.showSaveDialog(null);
    Path pth = jFile.getSelectedFile().toPath();
    JOptionPane.showMessageDialog(null, pth.toString());
    Graphics2D graphics2D = image2.createGraphics();
    try {
        ImageIO.write(image2, "", new File(pth.toString()));
    } catch (IOException ox) {
        // TODO: handle exception
        ox.printStackTrace();

}
}
}

采纳答案by u6294745

private void saveImage(){
    BufferedImage imagebuf=null;
    try {
        imagebuf = new Robot().createScreenCapture(panel.bounds());
    } catch (AWTException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }  
     Graphics2D graphics2D = imagebuf.createGraphics();
     panel.paint(graphics2D);
     try {
        ImageIO.write(imagebuf,"jpeg", new File("save1.jpeg"));
    } catch (Exception e) {
        // TODO Auto-generated catch block
        System.out.println("error");
    }
}

result example of snippet code

片段代码的结果示例

回答by nullptr

Create BufferedImage to store your painting. When you paint, paint on BufferedImage.

创建 BufferedImage 来存储您的绘画。绘画时,请在 BufferedImage 上绘画。

When you need to display paint on JPanel, draw BufferedImage on JPanel.

当需要在JPanel上显示paint时,在JPanel上绘制BufferedImage。

This way, you can load / save painting to file.

这样,您可以将绘画加载/保存到文件。

Something like this:

像这样的东西:

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class Paint extends JPanel{
    private BufferedImage paintImage = new BufferedImage(500, 400, BufferedImage.TYPE_3BYTE_BGR);

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(paintImage, 0, 0, null);
    }

    // draw painting
    public void updatePaint(){
        Graphics g = paintImage.createGraphics();

        // draw on paintImage using Graphics

        g.dispose();
        // repaint panel with new modified paint
        repaint();
    }

    public void save() throws IOException{
        ImageIO.write(paintImage, "PNG", new File("filename.png"));
    }

    public void load() throws IOException {
        paintImage = ImageIO.read(new File("filename.png"));
        // update panel with new paint image
        repaint();
    }
}

回答by camickr

Screen Imageallows you to save an image of any component.

屏幕图像允许您保存任何组件的图像。

回答by Sage

There is a nice approach:

有一个不错的方法:

BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
component.paint(g);
 try {
        ImageIO.write(image, "png", new File(filename));
    } catch (IOException ex) {
        Logger.getLogger(CustomApp.class.getName()).log(Level.SEVERE, null, ex);
   }

All what it does: It creates an image with visible component's size and ARGBtype for transparency support. Then it get the graphics and pass that to the component we want to have snapshot of. It paints that component's child component including anything drawn on it.

它所做的一切:它创建一个具有可见组件大小和ARGB类型的图像,以支持透明度。然后它获取图形并将其传递给我们想要快照的组件。它绘制该组件的子组件,包括在其上绘制的任何内容。

Update:You can use component.print(Graphics g) too:

更新:您也可以使用 component.print(Graphics g):

Dimension componentSize = component.getPreferredSize();
component.setSize(componentSize); // need to make sure that both sizes are equal
BufferedImage image = new BufferedImage(comonent.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
g.fillRect(0, 0, image.getWidth(), image.getHeight());
component.print(g);

But this function will draw only the rendered graphics of the component but not the child components. I have tested it.

但是这个函数只会绘制组件的渲染图形,而不是子组件。我已经测试过了。



Edit:

编辑:

  1. Your paint extends JFrameclass can have a nice name, e.g., PaintFrame extends JFrame. Class name should not have a name of a function, paint is a verb, it is a function.
  2. panel extends JPanel: why should we go down choosing a class name with first letter of lower case? We can give our component name to reflect what we are doing with it: like, we are drawing so what about MyCanvas extends JPanel
  3. Inside the panelyour first statement private paint my_paint;: what is it doing here unnecessarily ?
  4. your saveFile()function belongs to the JFrameand you have created your panel(on which you are drawing) local to the frame constructor. How should the saveFile()function have access to it? Declare your painting Panel in the JFrame class context as publicor private.
  5. I have written in a meaningful way to read the sizes of the component using getWidth()and getHeight()But you are writing:

         BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT, ...);
    
  1. 你的paint extends JFrame班级可以有一个好听的名字,例如,PaintFrame extends JFrame。类名不应该有函数名,paint 是一个verb,它是一个函数。
  2. panel extends JPanel: 为什么我们要往下选择首字母小写的类名?我们可以给我们的组件命名来反映我们正在用它做什么:比如,我们正在绘制,那么呢?MyCanvas extends JPanel
  3. panel您的第一个声明中private paint my_paint;:它在这里不必要地做什么?
  4. 您的saveFile()函数属于JFrame并且您已经在panel框架构造函数的本地创建了您的(您正在绘制的)。saveFile()函数应该如何访问它?在 JFrame 类上下文中将您的绘画面板声明为publicprivate
  5. 我以一种有意义的方式编写了使用getWidth()and读取组件大小的方法,getHeight()但是您正在编写:

         BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT, ...);
    

And again i have completely written the code how to save the image as a pngusing ImageIO.write(image, "png", "myFile.png")function. Please read the answers carefully.

我再次完整地编写了如何将图像保存为pngusingImageIO.write(image, "png", "myFile.png")函数的代码。请仔细阅读答案。

Following resources might be helpful:

以下资源可能会有所帮助:

  1. A closer look at painting mechanism.
  2. Writing and saving images
  1. 仔细看看绘画机制。
  2. 写入和保存图像