2

我一直在尝试制作一个简单的程序,它有一个类似画笔的工具,当打开它时创建了一个 JFrame 并在其中放置了一个 Canvas 用户可以绘制的地方。现在,我正在尝试使用在退出时调用的 saveCanvas 方法保存绘图,但无论我做什么,我都会得到一个黑色图像。这是我的代码:

public class Test{

    JFrame f;
    Canvas c;
    int x=-1, y=-1;

    public Test() {
        f = new JFrame();
        f.setSize(1200, 800);
        c = new Canvas(){
            @Override
            public void paint(Graphics g){
                super.paint(g);
            }
        };
        f.add(c);
        c.addMouseMotionListener(new MouseMotionListener(){    
            @Override
            public void mouseMoved(MouseEvent e) {
                // empty
            }
            @Override
            public void mouseDragged(MouseEvent e){
                if(x==-1){
                   x = e.getX();
                   y = e.getY();
                }
               c.getGraphics().fillOval(x, y, 5, 5); 
               x = e.getX();
               y = e.getY();
            }
        });
        f.addWindowListener(new WindowAdapter(){
           @Override
           public void windowClosing(WindowEvent evt) {
                 onExit();
           }
           public void onExit() 
            {
                saveCanvas(c);
                System.exit(0);
            }
        });
        f.setVisible(true);
    }

    public static void main(String[] args) {

        Test paintBrush = new Test();
    } 
    public static void saveCanvas(Canvas canvas){

        BufferedImage image=new BufferedImage(canvas.getWidth(), canvas.getHeight(),BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2=(Graphics2D)image.getGraphics();
                boolean x = false;
                while(!x){
                    x = g2.drawImage(image, 0, 0, null);
                }
        try 
                {
                    ImageIO.write(image, "png", new File("C:\\test\\canvas.png"));
        } 
                catch (Exception e) {

        }
    }
}

关于可能导致这种情况的任何想法?

4

2 回答 2

6

这是错误的:

            Graphics2D g2=(Graphics2D)image.getGraphics();
            boolean x = false;
            while(!x){
                x = g2.drawImage(image, 0, 0, null);
            }

你拿了Graphicsof ,image然后画image上了那个Graphics。所以基本上,你是在画image自己。

你想要的可能更像这样:

            Graphics2D g2=(Graphics2D)image.getGraphics();
            canvas.print(g2);
            ...

现在,还要考虑以下注释:

  • 不要使用Canvas(AWT) 而是使用JPanel(和覆盖paintComponent) 或JLabel使用(在 the上BufferedImage绘制并在 上调用) (Swing)GraphicsBufferedImagerepaint()JLabel
  • 不要getGraphics在任何组件上使用,使用方法中Graphics提供的paintComponent

我正在谈论的小演示示例:

import java.awt.Desktop;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class Test {

    JFrame f;
    JLabel c;
    BufferedImage image;
    int x = -1, y = -1;

    public Test() {
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        image = new BufferedImage(1200, 800, BufferedImage.TYPE_INT_ARGB);
        c = new JLabel(new ImageIcon(image));

        f.add(c);
        c.addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseMoved(MouseEvent e) {
                // empty
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                if (x == -1) {
                    x = e.getX();
                    y = e.getY();
                }
                image.getGraphics().fillOval(x, y, 5, 5);
                c.repaint();
                x = e.getX();
                y = e.getY();
            }
        });
        f.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent evt) {
                onExit();
            }

            public void onExit() {
                try {
                    File output = new File("C:\\test\\canvas.png");
                    if (!output.getParentFile().exists()) {
                        output.getParentFile().mkdirs();
                    }
                    ImageIO.write(image, "png", output);
                    Desktop.getDesktop().open(output);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        f.pack();
        f.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {

                Test paintBrush = new Test();
            }
        });
    }

}
于 2013-05-15T13:21:49.140 回答
1
    // Create a buffered image:
    BufferedImage image=new BufferedImage(canvas.getWidth(), 
        canvas.getHeight(),BufferedImage.TYPE_INT_ARGB);

    // Get the g2 to draw with on the image:
    Graphics2D g2= (Graphics2D)image.getGraphics();

    // Let the canvas component do a paintComponent on the image:
    SwingUtilities.paintComponent(g2, canvas, frame, 0, 0,
        canvas.getWidth(), canvas.getHeight());

    ImageIO.write(image, "png", new File("C:\\test\\canvas.png"));

而不是 Canvas(一个公认的误导性名称,尤其是现在使用 HTML 5)使用 JPanel。

在paintComponent 中,所有像fillOval 这样的绘图都必须完成。添加 Shape-s 或 - 更容易?- 添加描述必须绘制的数据。

有一些关于 Paint 程序的绘图教程。

于 2013-05-15T13:38:13.037 回答