class Bar {
String name;
int value;
public Bar(String name,int value) {
this.name=name;
this.value=value;
}
}
class Point{
public Point(float x,float y) {
this.x=x;
this.y=y;
}
float x;
float y;
}
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.imageio.ImageIO;
public class LineChartMaker {
private int width;
private int height;
private BufferedImage img;
private Graphics2D g2d;
private int yStart;
private int yEnd;
private List<Bar> bars;
public LineChartMaker(int width, int height, int yStart, int yEnd){
this.width = width;
this.height = height;
this.img = new BufferedImage(this.width,this.height,BufferedImage.TYPE_INT_RGB);
this.g2d = (Graphics2D)img.getGraphics();
this.yStart = yStart;
this.yEnd = yEnd;
}
public void addBar(String name, int value) {
if(bars == null) {
bars = new ArrayList<Bar>();
}
bars.add(new Bar(name, value));
}
private void resetCoordinate() {
AffineTransform trans = new AffineTransform();
trans.translate(0,this.height - this.yStart);
trans.rotate(getRad(180.0),0,0);
trans.scale(-1,1);
this.g2d.setTransform(trans);
}
public void draw() {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
resetCoordinate();
g2d.setColor(new Color(135,206,235));
g2d.fillRect(0, -this.yStart, this.width, this.height);
final int yMax = this.yEnd;
final int barCnt = this.bars.size();
final float stepx = this.width / barCnt;
final float CW = stepx / 3;
Stroke dashed = new BasicStroke(1,BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL,0,
new float[]{16, 4}, 0);
g2d.setColor(Color.gray);
for(int i = 0; i < barCnt; i++) {
float x = i * stepx;
float y = yMax;
g2d.setStroke(new BasicStroke(1.0f));
g2d.drawLine((int)x, 0, (int)x, (int)y);
g2d.setStroke(dashed);
g2d.drawLine((int)(x+CW), 0, (int)(x+CW), (int)y);
g2d.drawLine((int)(x+2*CW), 0, (int)(x+2*CW), (int)y);
}
float maxCnt = -1;
for(Bar b:bars) {
if(b.value > maxCnt) {
maxCnt = b.value;
}
}
final float ratio = yMax / maxCnt;
final float stepy = yMax / barCnt;
final float GH = stepy / 3;
for(int i = 0;i <= barCnt; i++){
float y = i * stepy;
g2d.setStroke(new BasicStroke(1.0f));
g2d.drawLine(0,(int)y, this.width, (int)y);
g2d.setFont(new Font("宋体",Font.BOLD,16));
g2d.setColor(Color.black);
int yValue=(int)(y * maxCnt / yMax);
putString(g2d,yValue+"",15,(int)y);
if(i > 0) {
g2d.setStroke(dashed);
g2d.drawLine(0,(int)(y-GH), this.width, (int)(y-GH));
g2d.drawLine(0,(int)(y-2*GH), this.width, (int)(y-2*GH));
}
}
List<Point> points = new ArrayList<>();
for(int i=0;i < this.bars.size();i++){
Bar bar = this.bars.get(i);
float x = i*stepx+(CW);
float y = 0;
float w = CW;
float h = bar.value*ratio;
g2d.setColor(getColor(i));
g2d.fillRect((int)x, (int)y, (int)(w), (int)(h));
float lx = x + CW / 2;
float ly = y + h;
points.add(new Point(lx, ly));
g2d.setFont(new Font("宋体",Font.BOLD,16));
g2d.setColor(Color.black);
putString(g2d,bar.name+"="+bar.value,(int)(x+CW/2),(int)(h-15));
}
for(int i = 0; i < points.size() - 1; i++) {
Point p1 = points.get(i);
Point p2 = points.get(i+1);
g2d.setColor(Color.black);
g2d.setStroke(new BasicStroke(2.0f));
g2d.drawLine((int)p1.x,(int)p1.y, (int)p2.x, (int)p2.y);
}
g2d.setFont(new Font("宋体",Font.BOLD,36));
g2d.setColor(Color.black);
putString(g2d,"高中科目成绩",this.width / 2,this.yEnd+50);
g2d.setFont(new Font("宋体",Font.BOLD,12));
g2d.setColor(Color.black);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = simpleDateFormat.format(new Date());
System.out.println(time);
putString(g2d,"绘制于" + time,this.width - 100,-25);
g2d.dispose();
}
public void write2File(String path) {
try {
ImageIO.write(img, "PNG", new FileOutputStream(path));
} catch (Exception e) {
e.printStackTrace();
}
}
private void putString(Graphics2D g2d,String text,int x,int y) {
AffineTransform previousTrans = g2d.getTransform();
AffineTransform newtrans = new AffineTransform();
FontMetrics fm2 = g2d.getFontMetrics();
int textWidth = fm2.stringWidth(text);
newtrans.translate(x - textWidth / 2, (this.height - this.yStart) - y);
g2d.setTransform(newtrans);
g2d.drawString(text,0,0);
g2d.setTransform(previousTrans);
}
private static double getRad(double degree) {
return degree * Math.PI / 180.0f;
}
private static Color getColor(int idx) {
Color[] colors= {Color.red,Color.yellow,Color.blue,Color.magenta,Color.green,Color.orange,Color.cyan};
int i = idx % colors.length;
return colors[i];
}
public static void main(String[] args) {
LineChartMaker pm = new LineChartMaker(1200 ,960 ,50 ,800);
pm.addBar("语文", 150);
pm.addBar("数学", 146);
pm.addBar("英语", 130);
pm.addBar("物理", 92);
pm.addBar("化学", 89);
pm.addBar("生物", 94);
pm.addBar("历史", 90);
pm.addBar("政治", 98);
pm.draw();
pm.write2File("E:\\test.png");
System.out.println("折线图已经已经生成");
}
}