【问题标题】:Save image from JPanel after draw绘制后从 JPanel 保存图像
【发布时间】:2013-10-27 17:31:37
【问题描述】:

我是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();

}
}
}

【问题讨论】:

  • 遵循标准 Java 命名约定。类名不要以小写字符开头。

标签: java swing bufferedimage


【解决方案1】:

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

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

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

类似这样的:

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

【讨论】:

    【解决方案2】:
    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");
        }
    }
    

    【讨论】:

    • 真的救了我的命!
    【解决方案3】:

    有一个不错的方法:

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

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

    更新:您也可以使用 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);
    

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


    编辑:

    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()getHeight() 以一种有意义的方式来读取组件的大小但是你在写:

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

    我已经完全编写了如何使用ImageIO.write(image, "png", "myFile.png") 函数将图像保存为png 的代码。 请仔细阅读答案。

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

    1. A closer look at painting mechanism.
    2. Writing and saving images

    【讨论】:

    • 我确实喜欢你的代码,但是当我打开默认程序保存的图像时,它显示一个背景颜色为黑色的图像! :(
    • 好的,您尝试绘制的组件是可见的?它需要使用setVisible(true) 显示组件。告诉我
    • Swing 组件,除了顶级组件(JFrame、JDialog、JWindow),默认是可见的。您不需要手动调用 setVisible() 方法。
    • @camickr,是的,我的意思是在他打算创建图像时它已经可见。我正在用另一种方法更新答案。它应该像我测试过的那样工作
    • @ĐăngNguyễn,我已经更新了答案。看看它是否适合你。
    【解决方案4】:

    Screen Image 允许您保存任何组件的图像。

    【讨论】:

    • 我想用windows的默认程序打开,但是打不开:(
    • 对我来说很好。我只是在使用 Windows 资源管理器时双击图像并显示图像。发布您的SSCCE 来证明问题。
    • 什么是 SSCCE !,我是新手 :(
    • @ĐăngNguyễn,你试过谷歌吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多