15

I'm trying to develop some sort of paint using Java.

I have a JComponent that is located inside of a JPanel.

I already can draw lines and rectangles into that JComponent.

Now, how can I export this drawings as an image (png, gif, jpg)?

I tried this:

BufferedImage b = new BufferedImage(1700,1100,BufferedImage.TYPE_INT_RGB);
this.print(getGraphics());
try{ImageIO.write(b,"png",new File("test.png"));}catch (Exception e) {}

But that only creates a .png file all black.

Help!!!

RESOLVED!!!

BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_ARGB); 
Graphics g = bi.createGraphics();
this.paint(g);  //this == JComponent
g.dispose();
try{ImageIO.write(bi,"png",new File("test.png"));}catch (Exception e) {}
tiiin4
  • 539
  • 4
  • 7
  • 19
  • 5
    You should accept Tedil's answer. – Dathan Sep 05 '12 at 00:34
  • All the call to `paint` works, the API for Java says *Applications should not invoke paint directly, but should instead use the repaint method to schedule the component for redrawing.* The problem is that it's hard to know when the update of the Graphics is finished, so that you can indeed save the correct BufferedImage. Some of my testing revealed that you can save a partially rendered BufferedImage as a PNG using this technique. – Fuhrmanator Jul 30 '13 at 17:33

2 Answers2

8

First of all, print() is the incorrect method. What I guess should work (haven't tested it yet) is: get the BufferedImage's Graphics (b.createGraphics()) and use that graphics object to paint() your panel/component.

(e.g. yourPanel.paint(b.createGraphics());)

Tedil
  • 1,935
  • 28
  • 32
-3

this is a demo:

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("serial")
public class DrawGraph extends JPanel {
    private static final int PREF_W = 1000;
    private static final int PREF_H = 800;
    private static final int BORDER_GAP = 25;
    private static final int PADDING = 25;
    private static final Color GRAPH_COLOR = Color.green;
    private static final Color GRAPH_POINT_COLOR = new Color(100, 100, 100, 180);
    private static final Color GRID_COLOR = new Color(200, 200, 200, 200);
    private static final Stroke GRAPH_STROKE = new BasicStroke(3f);
    private static final int GRAPH_POINT_WIDTH = 4;
    private static final int Y_HATCH_CNT = 10;
    private List<Double> scores;

    public DrawGraph(List<Double> scores2) {
        this.scores = scores2;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        double xScale = ((double) getWidth() - (2 * BORDER_GAP)-PADDING) / (scores.size() - 1);
        double yScale = ((double) getHeight() - (2 * BORDER_GAP)-PADDING) / (getMaxScore() - getMinScore());

        List<Point> graphPoints = new ArrayList<Point>();
        for (int i = 0; i < scores.size(); i++) {
            int x1 = (int) (i * xScale + BORDER_GAP + PADDING);
            int y1 = (int) ((getMaxScore() - scores.get(i)) * yScale + BORDER_GAP);
            graphPoints.add(new Point(x1, y1));
        }

        g2.setColor(Color.WHITE);
        g2.fillRect(BORDER_GAP + PADDING, BORDER_GAP, getWidth() - (2 * BORDER_GAP) - PADDING, getHeight() - 2 * BORDER_GAP - PADDING);
        g2.setColor(Color.BLACK);

        g2.drawLine(BORDER_GAP + PADDING, getHeight() - BORDER_GAP - PADDING, BORDER_GAP + PADDING, BORDER_GAP);
        g2.drawLine(BORDER_GAP + PADDING, getHeight() - BORDER_GAP - PADDING, getWidth() - BORDER_GAP, getHeight() - BORDER_GAP - PADDING);

        for (int i = 0; i < Y_HATCH_CNT + 1; i++) {
            int x0 = BORDER_GAP + PADDING;
            int x1 = GRAPH_POINT_WIDTH + BORDER_GAP + PADDING;
            int y0 = getHeight() - ((i * (getHeight() - BORDER_GAP * 2 - PADDING)) / Y_HATCH_CNT + BORDER_GAP + PADDING);
            int y1 = y0;
            if (scores.size() > 0) {
                g2.setColor(GRID_COLOR);
                g2.drawLine(BORDER_GAP + PADDING + 1 + GRAPH_POINT_WIDTH, y0, getWidth() - BORDER_GAP, y1);
                g2.setColor(Color.BLACK);
                String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 1.0) / Y_HATCH_CNT)) * 100)) / 100.0 + "";
                FontMetrics metrics = g2.getFontMetrics();
                int labelWidth = metrics.stringWidth(yLabel);
                g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3);
            }
            g2.drawLine(x0, y0, x1, y1);
        }

        for (int i = 0; i < scores.size(); i++) {
            if (scores.size() > 1) {
                int x0 = i * (getWidth() - BORDER_GAP * 2 - PADDING) / (scores.size() - 1) + BORDER_GAP + PADDING;
                int x1 = x0;
                int y0 = getHeight() - BORDER_GAP - PADDING;
                int y1 = y0 - GRAPH_POINT_WIDTH;
                if ((i % ((int) ((scores.size() / 20.0)) + 1)) == 0) {
                    g2.setColor(GRID_COLOR);
                    g2.drawLine(x0, getHeight() - BORDER_GAP - PADDING - 1 - GRAPH_POINT_WIDTH, x1, BORDER_GAP);
                    g2.setColor(Color.BLACK);
                    String xLabel = i + "";
                    FontMetrics metrics = g2.getFontMetrics();
                    int labelWidth = metrics.stringWidth(xLabel);
                    g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3);
                }
                g2.drawLine(x0, y0, x1, y1);
            }
        }

        Stroke oldStroke = g2.getStroke();
        g2.setColor(GRAPH_COLOR);
        g2.setStroke(GRAPH_STROKE);
        for (int i = 0; i < graphPoints.size() - 1; i++) {
            int x1 = graphPoints.get(i).x;
            int y1 = graphPoints.get(i).y;
            int x2 = graphPoints.get(i + 1).x;
            int y2 = graphPoints.get(i + 1).y;
            g2.drawLine(x1, y1, x2, y2);
        }

        g2.setStroke(oldStroke);
        g2.setColor(GRAPH_POINT_COLOR);
        for (int i = 0; i < graphPoints.size(); i++) {
            int x = graphPoints.get(i).x - GRAPH_POINT_WIDTH / 2;
            int y = graphPoints.get(i).y - GRAPH_POINT_WIDTH / 2;;
            int ovalW = GRAPH_POINT_WIDTH;
            int ovalH = GRAPH_POINT_WIDTH;
            g2.fillOval(x, y, ovalW, ovalH);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(PREF_W, PREF_H);
    }

    private double getMinScore() {
        double minScore = Double.MAX_VALUE;
        for (Double score : scores) {
            minScore = Math.min(minScore, score);
        }
        return minScore;
    }

    private double getMaxScore() {
        double maxScore = Double.MIN_VALUE;
        for (Double score : scores) {
            maxScore = Math.max(maxScore, score);
        }
        return maxScore;
    }

    public static void createAndShowGui(ArrayList<Double> scores, String s) {
        DrawGraph mainPanel = new DrawGraph(scores);

        JFrame frame = new JFrame(s);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.getContentPane().add(new JButton(new AbstractAction("Save Image") {
            @Override
            public void actionPerformed(ActionEvent e) {
                mainPanel.saveImage(new File("graph.png"));
            }
        }),BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public void saveImage(File file){
        BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_ARGB);
        Graphics g = bi.createGraphics();
        this.paint(g);
        g.dispose();
        try{
            ImageIO.write(bi,"png",file);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        final ArrayList<Double> inputValues = new ArrayList<Double>();
        inputValues.add(1d);
        inputValues.add(2d);
        // Read input values from text document and store in ArrayList
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                DrawGraph.createAndShowGui(inputValues, "MyGraphTitle");
            }
        });
    }
}

you can change it by youself.

Roman.Luo
  • 63
  • 5
  • This looks like a nearly verbatim copy of the code in this [question](http://stackoverflow.com/q/39490009/230513). – trashgod Sep 14 '16 at 14:21