Esta es una demostración:
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");
}
});
}
}
puede cambiar por ti mismo.
Deberías aceptar la respuesta de Tedil. – Dathan
Toda la llamada a 'pintura' funciona, la API para Java dice * Las aplicaciones no deberían invocar pintura directamente, sino que deberían usar el método de repintado para programar el componente para volver a dibujar. * El problema es que es difícil saber cuándo la actualización de la Gráfica está terminada, de modo que puede guardar la Imagen Buffered correcta. Algunas de mis pruebas revelaron que puede guardar una Imagen Buffered parcialmente renderizada como PNG usando esta técnica. – Fuhrmanator