Java:D2D实现绘制简单的直方图片

本文介绍了使用JavaAWT和Swing库创建一个折线图生成器类LineChartMaker,通过实例化对象并添加直方图数据,展示高中科目成绩的柱状图和折线图。
摘要由CSDN通过智能技术生成

在这里插入图片描述

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;


/****
 *** author:lao
 *** name:LineChartMaker
 *** date:2024/1/30  16:29
 *** filename:Main
 *** desc:折线图生成器
 ***/
public class LineChartMaker {
    // 图片宽度
    private int width;
    // 图片高度
    private int height;
    // img对象
    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;// 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));
            }
        }

        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();// 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) {
        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("折线图已经已经生成");
    }
}
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 这个问题是关于Excel公式的语法和功能的问题。 要用A66:A75的数据列绘制直方图,可以使用Excel的HISTOGRAM函数。该函数可以将数据分成不同的区间,并计算每个区间中的数值数量。然后,可以使用这些计数值创建一个频率分布直方图。 以下是使用HISTOGRAM函数创建直方图的公式: =HISTOGRAM(A66:A75,5) 其中,A66:A75是要绘制直方图的数据范围,5是要分成的区间数量。您可以根据需要更改区间数量。 请注意,HISTOGRAM函数仅适用于Excel 2016及更高版本。如果您使用较早的版本,则可以使用频率函数和数据分析工具来创建直方图。 ### 回答2: 要用A66:A75的数据列绘制直方图的Excel公式,可以按照以下步骤操作: 1. 打开Excel软件,创建一个新的工作表。 2. 在A66:A75的单元格范围内输入要绘制直方图的数据。 3. 在B66的单元格中,输入"直方图"以作为直方图的标题。 4. 在C66的单元格中,输入"区间"以标明直方图的区间。 5. 在D66的单元格中,输入"频数"以标明每个区间的数量。 6. 在C67的单元格中,输入"=MIN(A66:A75)"以获取数据列中的最小值。 7. 在C68的单元格中,输入"=MAX(A66:A75)"以获取数据列中的最大值。 8. 在C69的单元格中,输入"=(C$68-C$67)/5"以计算每个区间的宽度。这里以总范围的1/5作为区间的宽度,可以根据实际需求进行调整。 9. 在C70的单元格中,输入"=ROUNDUP((A66-C$67)/C$69,0)"以计算第一个数据在哪个区间。 10. 将公式C70拖动到C71:C75,以计算每个数据所在的区间。 11. 在D66的单元格中,输入"=COUNTIF(C70:C75,"=C67")"以计算第一个区间的频数。 12. 将公式D66拖动到D67:D75,以计算每个区间的频数。 13. 选中C66:D75的单元格范围,点击Excel的"插入"选项卡,选择"SXW图表"中的"直方图"图表类型,然后选择"创建图表"。 14. 在弹出的图表工作表中,可以进一步编辑和美化直方图的外观,包括调整颜色、添加图例等。 通过上述步骤,可以使用A66:A75的数据列绘制直方图的Excel公式。 ### 回答3: 要使用A66:A75的数据列绘制直方图的Excel公式,可以按照以下步骤进行操作: 1. 首先,在Excel中选择合适的区域来绘制直方图,例如,选中单元格C1作为直方图的起始位置。 2. 在C1单元格(或选择的合适起始位置)输入以下公式:=FREQUENCY(A66:A75, D1:D10),并按下回车键。 3. 在D1:D10单元格(或选择的合适位置)输入直方图的区间范围。例如,如果要将数据分成10个区间,可以在D1输入最小值,D10输入最大值,并在D2:D9依次输入其他区间的上限值。 4. 选中C1:C10单元格(或绘制直方图的区域),点击“插入”选项卡上的“图表”按钮,选择“柱形图”中的“集群柱形图”样式。 5. 点击“确定”按钮,即可生成直方图
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值