前言
今天整理资料,看到了之前自己用Java画了张雷达图,遂又拿来研究了下,感觉比较好玩,特地分享一下。
众所周知,Java在绘制图像方面的能力是比较差(la)劲(ji)的。自带的主要的一些图像处理类有Java2D中绘图类Graphics,图像流处理类ImageIO等。
有一些基于Java的图像处理开源包也仅仅是对原图像进行缩放、变化、水印等操作,使用Java进行绘图的少之又少。
今天我们用Java自带的图像处理类(Graphics、ImageIO等)来绘制一张雷达图吧。
正文
为什么要画雷达图?而不是用Java绘制动漫人物?
咳咳……因为雷达图应用广泛(就不要为难Java画动漫人物了TAT)。
我们开始吧,先随便看一张雷达图。
可知其主要内容:
外层环、圆环数量、圆环半径、分类名称、各个部分的数值、各种颜色等等很多很多属性。
这里,我们不妨绘制一个考试分数雷达图,这样更结合实际。
我们需要一个Java Bean,里面存放雷达图的一些属性参数。如下:
1 | /** |
上面省略掉了get set和构造方法。
另外我里面还有一些参数设置没提到的,主要是用来展示效果让其更人性化(应付客户使其更加满意)的,比如底部的分数击败直线,雷达图中央的分数显示等,一会儿大家可以看到效果。
参数很多,没办法……
对于每个分类,我们也新建一个属于它们的Java Bean,用来存储它们的属性。(PS:因为到底有多少分类是不确定的,故应该在画图时传入一个Bean List)。
如下:
1 | public class RadarMapData { |
同样省略了Get Set 和构造方法,我又增加了图片路径可以在分类的文字部分添加小图标,还可以对分类进行分组(比如数学是理科分组,语文英语是文科分组),可以说很Nice了(以应对莫名其妙的需求)。
好了,开始使用我们的Graphics类进行绘图等操作了。
首先,这个关键类要使用我们刚才的那两个Bean,应该如下代码,同样Get,Set和构造方法略。
1 | public class RadarMap { |
开始绘制逻辑,首先有个画圆环方法,可以画出数个同心圆,如下:
1 | /** |
主要方法就是g.drawOval画圆,不在详细解释。
然后我们以圆心绘制分类的每条射线,同时拿到每个分类的最大数值和这个人的数值并标记,然后连接这个人的各个数值,并将这个多边形内部填充起来。
如下:
1 | /** |
这个方法首先解析分类数组,有几个就画几条射线(根据角度,这里逆时针旋转,起始角度-90,也就是从正上方开始旋转),从圆心与角度点之间画直线,并为这条直线的终点(角度点)添加文字和图片(分类文字及图片,方法addCirWordPic)。
完成后对于各个实际值点(实际分,比如语文100分,实际78分,78就是这儿的实际值),绘制成多边形。
(PS: Polygon p = new Polygon();绘制多边形,p.addPoint为多边形添加指定点,g.drawPolygon(p)为绘制多边形,g.fillPolygon(p)为多边形填充颜色)
上面方法调用了两个方法getMappedPoint和addCirWordPic,大家可以看下,分别为寻找绘图点方法和添加分类图片文字方法。
1 | /** |
绘制分类图片及文字时,由于要考虑文字大小,图片宽度等要求,故对图片及文字位置做了微调,会显得代码多些。
然后我们再对圆心加上一些文字,比如总分多少分什么的,如下:
1 | /** |
总的来说就是找到圆心位置,根据字体大小,对字体位置进行调整。
然后我们再来绘制下面的跑分直线部分,如下:
1 | /** |
这个线就是比分用的,比如小明总分500分,击败了全班80%的童鞋,这种直线及文字。
也没啥内容,主要就是绘制直线,要求变换直线宽度及颜色,然后在线的两端添加文字,然后在底部添加必要文字。
(PS:这儿的底部文字可以设置的,我直接写死了,其实也可以当参数传进来)
这个方法里面也用到了几个小方法,如下:
1 | /** |
相当于对一些细节的操作优化,这儿就不一一介绍了。
然后在程序出图之前,我们先用Java中比较古老的JFrame看看图片的效果,方便调试“修图”。
在RadarMap里添加如下方法,这个方法只有JFrame测试时用到,当图调好了就可以删了,如下:
1 | /** |
很简单,依次调用上面的几个方法。
我们新建一个JFrame Test类,如下:
1 | /** |
这个Test主要就是给一些参数赋值。然后测试,可以看到结果如下图所所示,哈哈,还是蛮不错的。
这我们只在JFrame上测试了,我们的任务是生成图片,然后开始吧,在RadarMap里添加如下方法:
1 | /** |
这个方法主要就是利用了BufferedImage来生成一张图片。我们把刚才JFrame里的两行注掉的代码开启。
1 | //init.setImgPath("/Users/zhangwentong/Desktop/image.jpg"); |
再次启动JFrame类,可以看到生成图片啦。
哈哈,蛮不错的……
然后我们把你的分数……这句话的你动态传入姓名(比如小红……)。
然后新建分数MapTest如下:
1 | /** |
同时添加图标(我这里只添加了一个相同的,不同的也是可以的),新建map文件夹(用于存放雷达图)。如下:
运行测试类。打开map文件夹。
随便选一张查看。
总结
通过使用Java2D绘制雷达图,学到了Java2D的一些用途吧,虽然Java2D使用的很少,而且以后估计用的概率也不大,但是,我们就当一次对于Java程序的自娱自乐吧!
PS:Java图像处理方面确实很差,因为它的着重点不是这儿,而是大型Web项目,这篇文章的目的也不在于去理解Java2D的一些用途,而是通过一些学习,让我们知道,Java也是可以做一些莫名其妙的事情的,虽然不尽人意,也是,世界上哪有一种编程语言是完美的呢?