[置顶] Java2d画直角坐标系

时间:2022-09-05 21:52:45

最近项目用到java作图,首先想到的是利用开源插件jfreechart,文档收费,网上资料参差不齐,最后还是觉得采用java2D bufferedImage作图。 现在分享一下。

把一张图片分为border部分和主体部分,如下图所示:

[置顶]        Java2d画直角坐标系

定义一个边界类

/**
* Copyright (c) 2014, alax
* All Rights Reserved.
*/

package chapterOne.axis;
/**
*
* @author alax_app@yeah.net
* @Date 2014-3-18 下午11:41:10
*
*/
public class AxisBorder {

private int left;
private int right;
private int top;
private int bottom;

private int backgroundColor;//背景色

public AxisBorder(){

}

public AxisBorder(int left, int right, int top, int bottom,
int backgroundColor) {
super();
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.backgroundColor = backgroundColor;
}



public int getLeft() {
return left;
}

public void setLeft(int left) {
this.left = left;
}

public int getRight() {
return right;
}

public void setRight(int right) {
this.right = right;
}

public int getTop() {
return top;
}

public void setTop(int top) {
this.top = top;
}

public int getBottom() {
return bottom;
}

public void setBottom(int bottom) {
this.bottom = bottom;
}

public int getBackgroundColor() {
return backgroundColor;
}

public void setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
}

}

接下来定义坐标轴实例

/**
* Copyright (c) 2014, alax
* All Rights Reserved.
*/

package chapterOne.axis;

import java.util.Date;

/**
*
* @author alax_app@yeah.net
* @Date 2014-3-19 上午12:10:01
*
*/
public class Axis {
public static final String VALUE = "value";
public static final String DATETIME = "datetime";

private int lineColor;//y轴颜色
private int lineWidth;//y轴宽度
private String title;//y轴标题
private String type;//y轴类型 支持value 类型 和datetime类型

private double max;//最大值
private double min;//最小值

private int ticks;//刻度个数

private Date startDate;
private Date endDate;


private String labelFormat; //刻度值排版


public Axis(){

}



public Axis(int lineColor, int lineWidth, String title, String type,
double max, double min, int ticks, Date startDate, Date endDate,
String labelFormat) {
super();
this.lineColor = lineColor;
this.lineWidth = lineWidth;
this.title = title;
this.type = type;
this.max = max;
this.min = min;
this.ticks = ticks;
this.startDate = startDate;
this.endDate = endDate;
this.labelFormat = labelFormat;
}






public int getLineColor() {
return lineColor;
}

public void setLineColor(int lineColor) {
this.lineColor = lineColor;
}

public int getLineWidth() {
return lineWidth;
}

public void setLineWidth(int lineWidth) {
this.lineWidth = lineWidth;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public double getMax() {
return max;
}

public void setMax(double max) {
this.max = max;
}

public double getMin() {
return min;
}

public void setMin(double min) {
this.min = min;
}


public String getLabelFormat() {
return labelFormat;
}

public void setLabelFormat(String labelFormat) {
this.labelFormat = labelFormat;
}


public Date getStartDate() {
return startDate;
}


public void setStartDate(Date startDate) {
this.startDate = startDate;
}


public Date getEndDate() {
return endDate;
}

public void setEndDate(Date endDate) {
this.endDate = endDate;
}


public int getTicks() {
return ticks;
}


public void setTicks(int ticks) {
this.ticks = ticks;
}


}

定义点

/**
* Copyright (c) 2014, alax
* All Rights Reserved.
*/

package chapterOne.axis;
/**
*
* @author alax_app@yeah.net
* @Date 2014-3-19 上午12:35:20
*
*/
public class Point {

private int x;
private int y;


public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}

}

画利用bufferedImage画坐标

/**
* Copyright (c) 2014, alax
* All Rights Reserved.
*/

package chapterOne.axis;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.imageio.ImageIO;

/**
*
* @author alax_app@yeah.net
* @Date 2014-3-19 上午12:30:20
*
*/
public class AxisUtils {


public static void main(String[] args) throws Exception {
int width = 1000;
int height = 400;
AxisBorder axisBorder = new AxisBorder(60, 60, 40, 40, 0xffffff);
BufferedImage bufferedImage = new BufferedImage(width+axisBorder.getLeft() + axisBorder.getRight(),
height + axisBorder.getTop() +axisBorder.getBottom(), BufferedImage.TYPE_INT_RGB);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

Graphics2D g = bufferedImage.createGraphics();
Date startDate = sdf.parse("20140318120000");
Date endDate = sdf.parse("20140320120000");
Axis xAxis = new Axis(0x000000, 2, "时间", "datetime", 0, 0, 5, startDate, endDate, "");
Axis yAxis = new Axis(0x000000, 2, "高度", "value", 30, 0, 5, null, null, "");
drawAxis(axisBorder, xAxis, yAxis, width, height, g);

//导出图片
String pathname = "E:\\config\\test.jpg";
ImageIO.write(bufferedImage, "jpg", new File(pathname));

}
public static void drawAxis(AxisBorder border ,Axis xaxis, Axis yaxis, int width, int height, Graphics2D g){
//抗锯齿 字体更平滑
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawBorder(border, width, height, g);
drawXAxis(border, xaxis, width, height, g);
drawYAxis(border, yaxis, width, height, g);
//设置作图区域颜色为白色
g.setColor(new Color(0xFFFFFF));
g.fillRect(border.getLeft(), border.getTop(), width, height);
}

/**
* 画x轴坐标
* @param axisBorder
* @param xaxis
* @param width
* @param height
* @param g
*/
private static void drawXAxis(AxisBorder axisBorder,
Axis xaxis, int width ,int height, Graphics2D g){
//画x坐标
Point point1 = new Point(axisBorder.getLeft(), axisBorder.getTop() + height);
Point point2 = new Point(axisBorder.getLeft() + width, axisBorder.getTop() + height);
drawLine(point1, point2, new Color(xaxis.getLineColor()) , xaxis.getLineWidth(), g);
//画刻度
int ticks = xaxis.getTicks();
int skips = width / ticks;
int x = axisBorder.getLeft();
int y1 = axisBorder.getTop() + height ;
int y2 = y1 + 10;
String type = xaxis.getType();//获取坐标轴类型
for(int i = 1 ; i <= ticks ; i++){
point1 = new Point(x + skips * i,y1);
point2 = new Point(x + skips * i,y2);
drawLine(point1, point2, new Color(xaxis.getLineColor()) , xaxis.getLineWidth(), g);

}
//画label
if(type.equals(Axis.VALUE)){
double vskips = (xaxis.getMax() - xaxis.getMin() ) / ticks + xaxis.getMin();
for(int i = 1 ; i <= ticks ; i++){
drawString(g, x + skips * i, y2, getValueLabel(vskips * i + xaxis.getMin(), xaxis.getLabelFormat()));
}
}else if(type.equals(Axis.DATETIME)){
long t0 = xaxis.getStartDate().getTime() ;
long tskips = ( xaxis.getEndDate().getTime() - t0 ) /ticks;
Calendar c = Calendar.getInstance();
for(int i = 1 ; i <= ticks ; i++){
c.setTimeInMillis(t0 + i * tskips);
drawString(g, x + skips * i, y2+10, getDateLabel(c.getTime(), xaxis.getLabelFormat()));
}
}
//画title
drawString(g, axisBorder.getLeft(),
axisBorder.getTop() + height + axisBorder.getBottom() /2, xaxis.getTitle());

}


/**
* 画Y轴坐标
* @param axisBorder
* @param yaxis
* @param width
* @param height
* @param g
*/
private static void drawYAxis(AxisBorder axisBorder,
Axis axis, int width ,int height, Graphics2D g){
//画x坐标
Point point1 = new Point(axisBorder.getLeft(), axisBorder.getTop() + height);
Point point2 = new Point(axisBorder.getLeft(), axisBorder.getTop());


drawLine(point1, point2, new Color(axis.getLineColor()) , axis.getLineWidth(), g);

//画刻度
int ticks = axis.getTicks();
int skips = height / ticks;
int x1 = axisBorder.getLeft();
int x2 = x1 - 10 ;
int y1 = axisBorder.getTop() + height ;
String type = axis.getType();//获取坐标轴类型
for(int i = 1 ; i <= ticks ; i++){
point1 = new Point(x2,y1 - skips * i);
point2 = new Point(x1,y1 - skips * i);
drawLine(point1, point2, new Color(axis.getLineColor()) , axis.getLineWidth(), g);

}
//画label
if(type.equals(Axis.VALUE)){
double vskips = (axis.getMax() - axis.getMin() ) / ticks + axis.getMin();
for(int i = 1 ; i <= ticks ; i++){
drawString(g, x2 - 20 , y1 - skips * i, getValueLabel(vskips * i + axis.getMin(), axis.getLabelFormat()));
}
}else if(type.equals(Axis.DATETIME)){
long t0 = axis.getStartDate().getTime() ;
long tskips = ( axis.getEndDate().getTime() - t0 ) /ticks;
Calendar c = Calendar.getInstance();
for(int i = 1 ; i <= ticks ; i++){
c.setTimeInMillis(t0 + i * tskips);
drawString(g, x2 - 20 , y1 - skips * i, getDateLabel(c.getTime(), axis.getLabelFormat()));
}
}
//画title
//画y坐标title
int x = Math.min(30, axisBorder.getLeft());
int y0 = axisBorder.getTop() + height/2 + 80;

//逆时针旋转180度
g.rotate(-Math.PI/2, x, y0);
Font font = new Font("宋体", Font.BOLD, 16);
g.setFont(font);
g.drawString(axis.getTitle(),x,y0);
//恢复画布,顺时针旋转180度
g.rotate(Math.PI/2,x,y0);

}

/**
* 画线
* @param point1
* @param point2
* @param lineColor
* @param lineWidth
* @param g
*/
private static void drawLine(Point point1 , Point point2, Color lineColor, int lineWidth ,Graphics2D g){
g.setStroke(new BasicStroke(lineWidth));
g.setColor(lineColor);
g.drawLine(point1.getX(), point1.getY(), point2.getX(), point2.getY());
}

/**
* 写字符
*/
private static void drawString(Graphics2D g,int x ,int y,String str){
g.drawString(str, x, y);
}



/**
* 获取数字型label
* @param value
* @param format
* @return
*/
public static String getValueLabel(double value , String format ){
if(format == null || format.equals("")){
return value +"";
}
return String.format(format, value+"");
}

/**
* 获取时间类型label
* @param date
* @param format
* @return
*/
public static String getDateLabel(Date date , String format){
SimpleDateFormat sdf = new SimpleDateFormat("dd");
if(format == null || format.equals("")){
format = "dd日HH时";
}
sdf.applyPattern(format);
return sdf.format(date);
}

/**
* 画border
* @param border
* @param width
* @param height
* @param g
*/
public static void drawBorder(AxisBorder border, int width, int height,Graphics2D g){
g.setColor(new Color(border.getBackgroundColor()));
g.fillRect(0, 0, border.getLeft(), border.getTop()+height+border.getBottom()); //填充背景色
g.fillRect(border.getLeft(), 0, width+border.getRight(), border.getTop());
g.fillRect(border.getLeft(), border.getTop()+height, width+border.getRight(), border.getBottom());
g.fillRect(border.getLeft()+width, border.getTop(), border.getRight(), height);
}

}

测试方法

public static void main(String[] args) throws Exception {
int width = 1000;
int height = 400;
AxisBorder axisBorder = new AxisBorder(60, 60, 40, 40, 0xffffff);
BufferedImage bufferedImage = new BufferedImage(width+axisBorder.getLeft() + axisBorder.getRight(),
height + axisBorder.getTop() +axisBorder.getBottom(), BufferedImage.TYPE_INT_RGB);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

Graphics2D g = bufferedImage.createGraphics();
Date startDate = sdf.parse("20140318120000");
Date endDate = sdf.parse("20140320120000");
Axis xAxis = new Axis(0x000000, 2, "时间", "datetime", 0, 0, 5, startDate, endDate, "");
Axis yAxis = new Axis(0x000000, 2, "高度", "value", 30, 0, 5, null, null, "");
drawAxis(axisBorder, xAxis, yAxis, width, height, g);

//导出图片
String pathname = "E:\\config\\test.jpg";
ImageIO.write(bufferedImage, "jpg", new File(pathname));

}

最终效果图如下

[置顶]        Java2d画直角坐标系