无法在Java中将当前画布数据转换为图像

5

我有一个简单的应用程序,允许用户在画布控件中绘图。

现在,我想将该画布转换为图像。以下是我的代码:

public void paint(Graphics g)
{
    //super.paint(g);
    Graphics2D draw = (Graphics2D) g;
    if(this.is_beginning || this.to_save)
    {
        draw.setColor(Color.white);
        draw.fillRect(0, 0, this.getWidth(), this.getHeight());
        this.is_beginning= false;
    }
    if(this.m_alzada)
    {
        draw.setColor(Color.red);
        draw.drawLine(uX, uY, x, y);

    }
}

这是我保存图片的方法。
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    int w = canvas1.getWidth();
    int h = canvas1.getHeight();
    int type = BufferedImage.TYPE_INT_BGR;
    BufferedImage image = new BufferedImage(w,h,type);
    Graphics2D g2 = image.createGraphics(); 
    canvas1.to_save = true;
    canvas1.paint(g2);
    try {
        ImageIO.write(image, "png", new File("C:/Users/Uriel/Desktop/ejemplo.png"));
    } catch (IOException ex) {
        Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
    }

}

所有这些都导致了一张空白的图像。我知道paint方法是如何工作的,并且意识到我的问题就在那里。但是,我该如何在paint方法中绘制用户已经绘制的所有内容呢?
对不起,我的英语不好,我来自墨西哥。顺便说一下,谢谢。
我想知道是否有办法做出类似于使用HTML5 Canvas时获得画布中每个像素的RGB信息矩阵的功能。在JAVA的Canvas组件中是否可能?

  1. 为了更快得到帮助,请发布一个[SSCCE](http://sscce.org/)。 2)“对不起我的英文不好,我来自墨西哥。” 一样。我来自澳大利亚。;)
- Andrew Thompson
如果 !this.m_alzada,那么图像将是白色的! - Andrew Thompson
我将搜索有关SSCCE的信息,因为网页对我无法打开。这个“this.m_alzada”是一个布尔变量,用于确定用户是否想在画布上绘制,它始终为真。我将使用一个按钮来改变它的状态,但首先我需要让它工作。 - Uriel Hernández
1个回答

6
除了确保组件大小合适之外,使用JComponent#printJComponent#printAll方法。这些方法会禁用双缓冲并克服一些本地对等体问题,当它期望打印到屏幕时。

更新

从示例应用程序中...

enter image description here

我能够生成这个转储

enter image description here

使用这段代码
Container pane = frame.getContentPane();
BufferedImage img = new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
pane.printAll(g2d);
g2d.dispose();
try {
    ImageIO.write(img, "png", new File("save.png"));
} catch (IOException ex) {
    ex.printStackTrace();
}

更新

我认为你的问题并不是来自于你的绘画软件。虽然它不够干净。

首先,你的“绘画”界面是从java.awt.Canvas延伸而来的,并且你正在将它添加到一个JFrame中,混合重量和轻量级组件从来都不是一个好主意。

public class Dibujo extends Canvas ...

你最好使用类似于 JPanel 的东西

public class Dibujo extends JPanel ...

永远不要这样做

public void paint(Graphics g) {
    //super.paint(g);

你必须调用super.paint,因为在后台进行的不仅仅是填充组件。一旦你开始使用像JPanel这样的东西,你就会想要重写paintComponent

你的绘制方法中只绘制了最后一条线段...

if (this.m_alzada) {
    draw.setColor(Color.
    draw.drawLine(uX, uY, x, y);
}

这意味着当您尝试保存组件时,您只会看到最后一个部分。每次调用paint方法时,应该绘制所有线段。
在您的mouseDragged方法中,您正在执行以下操作...
this.paint(this.getGraphics());

不要这样做。你不需要负责更新图形,重绘管理器会处理这些事情。它所做的基本上是在一个临时的图形上下文中进行绘制,一旦下一个重绘请求被处理,它就会被全部清除。

我认为你需要阅读执行自定义绘画以了解一些基本概念。我还建议你阅读AWT和Swing中的绘画,以了解Java中的绘画工作原理。

在修改你的代码后,我得到了这个结果...

enter image description here

像这样保存...

enter image description here

package prueba_uno_graphics;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.*;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;

/**
 *
 * @author Uriel
 */
// Don't mix heavy and light weight components
public class Dibujo extends JPanel implements ActionListener, MouseListener, MouseMotionListener {

//    ArrayList lineas = new ArrayList();
//    boolean m_alzada = true, is_beginning = true, to_save = false;
//    int uX, uY, x, y;

    private Path2D shape;

    Dibujo() {
        setBackground(Color.WHITE);
        shape = new Path2D.Float();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D draw = (Graphics2D) g;
//        if (this.is_beginning || this.to_save) {
//            draw.setColor(Color.white);
//            draw.fillRect(0, 0, this.getWidth(), this.getHeight());
//            this.is_beginning = false;
//        }
//        if (this.m_alzada) {
//            draw.setColor(Color.red);
//            draw.drawLine(uX, uY, x, y);
//
//        }

        draw.setColor(Color.RED);
        draw.draw(shape);

    }

//    @Override
//    public void paint(Graphics g) {
//        // ALWAYS call super.paint
//        super.paint(g);
//        Graphics2D draw = (Graphics2D) g;
//        if (this.is_beginning || this.to_save) {
//            draw.setColor(Color.white);
//            draw.fillRect(0, 0, this.getWidth(), this.getHeight());
//            this.is_beginning = false;
//        }
//        if (this.m_alzada) {
//            draw.setColor(Color.red);
//            draw.drawLine(uX, uY, x, y);
//
//        }
//    }

    @Override
    public void actionPerformed(ActionEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        //        this.uX = e.getX();
        //        this.uY = e.getY();
        Point point = e.getPoint();
        shape.moveTo(point.x, point.y);

    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        //        this.x = e.getX();
        //        this.y = e.getY();
        // Don't do this!
        //        this.paint(this.getGraphics());
        //        ArrayList ayuda = new ArrayList();
        //        ayuda.add(uX);
        //        ayuda.add(uY);
        //        ayuda.add(x);
        //        ayuda.add(y);
        //        this.lineas.add(ayuda);
        //        uX = x;
        //        uY = y;
        Point point = e.getPoint();
        shape.lineTo(point.x, point.y);
        repaint();

    }

    @Override
    public void mouseMoved(MouseEvent e) {
    }

}

我尝试使用Print,结果是一样的。我认为,当您调用paint或print方法时,它会进入print方法并绘制其中所述的内容。我认为我还不太明白这是如何工作的。 - Uriel Hernández
有两件事引起了我的注意,你正在使用 TYPE_INT_BGR 图像类型,虽然可能不是很重要,但它可能会让你后悔。另一件事是在写入图像之前你正在处理图形上下文。这可能有助于“关闭”图形并使其准备好保存。 - MadProgrammer
非常感谢您的帮助,MadProgrammer,但是您的优秀示例和我的作业之间有所不同。如果您有时间,我已经将我的代码上传到了Github https://github.com/urielhdz/Java-Paint-Application,甚至在那里我也放置了您的代码示例生成的图像。正如您所看到的,它没有考虑画布和用户绘制的内容。 - Uriel Hernández
太棒了,非常感谢。你说得对,我的基础不是JAVA程序员,我在HTML5中使用Canvas工作了很多,但现在我意识到它与JAVA的行为非常不同。我想给你一些钱,但我现在没有,我非常感激你的帮助,非常感谢! - Uriel Hernández
这对我很有帮助,谢谢你,还要为Megatokyo的例子点赞。 - EpicPandaForce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接