简体   繁体   中英

Java BufferedImage returns black image from Canvas

I've been trying to make a simple program that has a paint brush like tool, when opened it created a JFrame and in it i place a Canvas where the user gets to draw. Now, I'm trying to save the drawing using the saveCanvas method which is called on exit but whatever I do i get a black image as a result. Here's my code :

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

        }
    }
}

Any thoughts on what may be causing this?

Here is what is wrong:

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

You take the Graphics of image and you draw image onto that Graphics . So basically, you are drawing the image on itself.

what you want is probably more like this:

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

Now, consider the following remarks as well:

  • Don't use Canvas (AWT) but use instead JPanel (and override paintComponent ) or JLabel with a BufferedImage (draw on the Graphics of the BufferedImage and call repaint() on the JLabel ) (Swing)
  • Don't use getGraphics on any component, use the Graphics provided in the paintComponent method

Small demo example of what I am talking about:

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

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

Instead of a Canvas (an admittedly misleading name, especially now with HTML 5) use a JPanel.

In the paintComponent all drawing like fillOval has to be done. Add Shape-s or - easier? - add data describing what has to be drawn.

There are some drawing tutorials on Paint programs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM