先上图:
代码:
package graphics; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; class Bar{ String name; int value; public Bar(String name,int value) { this.name=name; this.value=value; } } /** * 直方图生成器 * @author ufo * 2022年1月31日 */ public class BarchartMaker { // 图片宽度 private int width; // 图片高度 private int height; // img对象 private BufferedImage img; // 绘图环境 private Graphics2D g2d; // 垂直方向起点 private int yStart; // 垂直方向终点 private int yEnd; // 直方图数据 private List<Bar> bars; // 构造函数 public BarchartMaker(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 resetCoodinate() { 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() { resetCoodinate(); // 设置背景为天蓝色 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;// CW:Column Width // LINE_TYPE_DASHED 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;// GH:Grid Width 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)); } } // --往下是画柱状图 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)); // 在柱子顶写文字 g2d.setFont(new Font("宋体",Font.BOLD,16)); g2d.setColor(Color.black); putString(g2d,bar.name+"="+bar.value,(int)(x+CW/2),(int)(h-15)); } // 写标题 g2d.setFont(new Font("宋体",Font.BOLD,36)); g2d.setColor(Color.black); putString(g2d,"g2d绘制直方图示例",this.width/2,this.yEnd+50); // 写作者 g2d.setFont(new Font("宋体",Font.BOLD,12)); g2d.setColor(Color.black); putString(g2d,"逆火绘制于2022年1月31日",this.width-100,-25); g2d.dispose();// g2d使命完成 } // 写入图片 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) { BarchartMaker pm=new BarchartMaker(1200,960,50,800); pm.addBar("勇气", 80); pm.addBar("毅力", 120); pm.addBar("果敢", 450); pm.addBar("机敏", 32); pm.addBar("决心", 360); pm.addBar("明智", 230); pm.addBar("忍耐", 420); pm.draw(); pm.write2File("c:\\hy\\4.png"); System.out.println("直方图做成"); } }
谨以以上代码纪念即将逝去的牛年,愿各位读者在新年里都健康多福!
2022年1月31日19点44分
END