【问题标题】:Cannot convert current canvas data into image in java无法在java中将当前画布数据转换为图像
【发布时间】:2012-10-10 15:44:24
【问题描述】:

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

现在,我想要的是将该画布转换为图像。这是我的代码。

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方法中绘制的所有内容?

对不起,我的英语不好,我来自墨西哥。顺便谢谢。

我想知道是否有任何东西可以制作,例如当您使用 Canvas og HTML5 时,您会得到一个包含画布中每个像素的 RGB 信息的矩阵。 JAVA中的canvas组件可以做到吗?

【问题讨论】:

  • 1) 为了尽快获得更好的帮助,请发帖 SSCCE。 2) “对不起,我的英语不好,我来自墨西哥。” 同上。我来自澳大利亚。 ;)
  • 如果!this.m_alzada 图像将是白色的!
  • 我将搜索 abotu sscce,因为该网页无法为我打开。好吧,this.m_alzada 是一个布尔变量,将用于知道用户是否想要在画布上绘制,它总是正确的,我将用一个按钮来改变它的状态,但首先我需要做这个工作。

标签: java image png


【解决方案1】:

除了确保组件大小合适外,请改用JComponent#printJComponent#printAll 方法。

这些将禁用双缓冲,并在它期望打印到屏幕时解决其他一些本机对等问题

更新

来自示例应用程序...

我能够生成这个转储

使用此代码

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

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

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

这意味着当您尝试保存组件时,您只会看到最后一段。 paint 方法应在每次调用时绘制所有线段。

在您的 mouseDragged 方法中,您正在执行此操作...

this.paint(this.getGraphics());

不要。您不负责更新图形,重绘管理器负责。所有这一切基本上都是在便签本图形上下文上进行绘制,一旦处理下一个重绘请求,它将全部被清除。

我认为您需要阅读Performing Custom Painting 以了解一些基本概念。我还会通读 Painting in AWT and Swing 以了解绘画在 Java 中的工作原理。

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

要这样保存...

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

}

【讨论】:

  • 我尝试了打印,结果是一样的。我在想,当你调用 paint 或 print 方法时,它会来到 print 方法并在其中绘制它所说的内容。我想我不太了解它是如何工作的。
  • 有两件事让我突然想到,你使用TYPE_INT_BGR 的图像类型,虽然可能没什么大不了的,但它可能会回来困扰你,另一个是你正在处理图形写图像之前的上下文。这可能有助于“关闭”图形并使其准备好保存
  • 非常感谢您对 MadProgrammer 的帮助,但是您的出色示例和我的作业之间有些不同。如果您有时间,我将我的代码上传到 github github.com/urielhdz/Java-Paint-Application 即使在那里我把您的代码示例结果的图像放在那里。如您所见,它没有计算 Canvas 和用户绘制的内容。
  • 太棒了,非常感谢。你对我的基础是正确的,我不是 JAVA 程序员,我在 HTML5 中使用 Canvas 做了很多工作,但现在我意识到它与 JAVA 的行为完全不同。我想给你一些钱,但我现在不在,非常感谢你的帮助,非常感谢!
  • 有机会请accept回答。 (这是@Mad 刚刚评论的另一种说法,但我喜欢用漂亮的动画 GIF 链接到答案。一张图片描绘了一千个单词,因此动画 GIF 必须至少描绘几千个。;) )
猜你喜欢
  • 1970-01-01
  • 2020-05-14
  • 2016-05-08
  • 2011-04-30
  • 2017-08-05
  • 2018-06-09
  • 2014-01-11
  • 1970-01-01
相关资源
最近更新 更多