Some work done on charts
This commit is contained in:
parent
3df20257b0
commit
eb30472a76
5 changed files with 221 additions and 182 deletions
|
|
@ -33,7 +33,6 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
public abstract class AbstractChart extends JPanel{
|
public abstract class AbstractChart extends JPanel{
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/** The offset from the borders of the panel in pixels */
|
/** The offset from the borders of the panel in pixels */
|
||||||
public static final int PADDING = 20;
|
public static final int PADDING = 20;
|
||||||
|
|
@ -47,71 +46,23 @@ public abstract class AbstractChart extends JPanel{
|
||||||
|
|
||||||
protected void paintComponent(Graphics g){
|
protected void paintComponent(Graphics g){
|
||||||
Graphics2D g2 = (Graphics2D) g;
|
Graphics2D g2 = (Graphics2D) g;
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
|
||||||
|
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||||
|
|
||||||
Rectangle bound = drawScale( g2 );
|
Rectangle bound = drawAxis( g2, new Rectangle(0, 0, getWidth(), getHeight()));
|
||||||
drawChart( g2, bound );
|
drawChart( g2, bound );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Rectangle drawScale(Graphics2D g2){
|
|
||||||
if( data == null )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// update values
|
/**
|
||||||
width = this.getWidth();
|
* This method will draw the axis of the chart
|
||||||
height = this.getHeight();
|
*
|
||||||
Rectangle bound = new Rectangle();
|
* @param g2 is the Graphics object that will paint the chart
|
||||||
|
* @param bound is the bounds of the axis, the drawing should not exceed this bound
|
||||||
// Values
|
|
||||||
int stepLength = 7;
|
|
||||||
|
|
||||||
/////// Temp values
|
|
||||||
// Calculate Font sizes
|
|
||||||
FontMetrics metric = g2.getFontMetrics();
|
|
||||||
int fontHeight = metric.getHeight();
|
|
||||||
int fontXWidth = 0;
|
|
||||||
int fontYWidth = 0;
|
|
||||||
for( Point p : data.getPoints() ){
|
|
||||||
int length = 0;
|
|
||||||
String tmp = data.getXString( p.x );
|
|
||||||
if( tmp != null ) length = metric.stringWidth( tmp );
|
|
||||||
else length = metric.stringWidth( ""+p.x );
|
|
||||||
fontXWidth = Math.max(length, fontXWidth);
|
|
||||||
|
|
||||||
tmp = data.getXString( p.y );
|
|
||||||
if( tmp != null ) length = metric.stringWidth( tmp );
|
|
||||||
else length = metric.stringWidth( ""+p.y );
|
|
||||||
fontYWidth = Math.max(length, fontYWidth);
|
|
||||||
}
|
|
||||||
// Calculate origo
|
|
||||||
Point origo = new Point( PADDING+fontYWidth+stepLength, height-PADDING-fontHeight-stepLength );
|
|
||||||
bound.x = (int) (origo.getX()+1);
|
|
||||||
bound.y = PADDING;
|
|
||||||
bound.width = width-bound.x-PADDING;
|
|
||||||
bound.height = (int) (origo.getY()-PADDING-1);
|
|
||||||
// Calculate Axis scales
|
|
||||||
double xScale = (double)(Math.abs(data.getMaxX())+Math.abs(data.getMinX()))/bound.width;
|
|
||||||
double yScale = (double)(Math.abs(data.getMaxY())+Math.abs(data.getMinY()))/bound.height;
|
|
||||||
|
|
||||||
|
|
||||||
/////// Draw
|
|
||||||
// Y Axis
|
|
||||||
g2.draw( new Line2D.Double( origo.getX(), PADDING, origo.getX(), origo.getY() ));
|
|
||||||
// X Axis
|
|
||||||
g2.draw( new Line2D.Double( origo.getX(), origo.getY(), width-PADDING, origo.getY() ));
|
|
||||||
// Y Axis steps and labels
|
|
||||||
g2.draw( new Line2D.Double( origo.getX(), origo.getY(), origo.getX()-stepLength, origo.getY() ));
|
|
||||||
g2.draw( new Line2D.Double( origo.getX(), PADDING, origo.getX()-stepLength, PADDING ));
|
|
||||||
|
|
||||||
// X Axis steps and labels
|
|
||||||
g2.draw( new Line2D.Double( width-PADDING, origo.getY(), width-PADDING, origo.getY()+stepLength ));
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
/*
|
|
||||||
g2.setColor(Color.red);
|
|
||||||
g2.drawRect(bound.x, bound.y, bound.width, bound.height);
|
|
||||||
*/
|
*/
|
||||||
return bound;
|
protected abstract Rectangle drawAxis(Graphics2D g2, Rectangle bound);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called after the chart scale has been drawn.
|
* This method is called after the chart scale has been drawn.
|
||||||
|
|
@ -136,19 +87,31 @@ public abstract class AbstractChart extends JPanel{
|
||||||
* Converts a x value to a x pixel coordinate
|
* Converts a x value to a x pixel coordinate
|
||||||
*
|
*
|
||||||
* @param x is the x data value
|
* @param x is the x data value
|
||||||
* @return pixel coordinate, or 0 if the chart have not been drawn yet.
|
* @param scale is the data scale
|
||||||
|
* @param bound is the drawing boundds
|
||||||
|
* @return a x pixel coordinate
|
||||||
*/
|
*/
|
||||||
protected int getXCoordinate(int x){
|
static protected double getXCoordinate(double x, double scale, Rectangle bound){
|
||||||
return 0;
|
return bound.x + x * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a y value to a y pixel coordinate
|
* Converts a y value to a y pixel coordinate
|
||||||
*
|
*
|
||||||
* @param y is the y data value
|
* @param y is the y data value
|
||||||
* @return pixel coordinate, or 0 if the chart have not been drawn yet.
|
* @param scale is the data scale
|
||||||
|
* @param bound is the drawing boundds
|
||||||
|
* @return a y pixel coordinate
|
||||||
*/
|
*/
|
||||||
protected int getYCoordinate(int y){
|
static protected double getYCoordinate(double y, double scale, Rectangle bound){
|
||||||
return 0;
|
return bound.y + bound.height - ( y * scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected double getXScale(ChartData data, Rectangle bound){
|
||||||
|
return (double) bound.width / (Math.abs(data.getMaxX()) + Math.abs(data.getMinX()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected double getYScale(ChartData data, Rectangle bound){
|
||||||
|
return (double) bound.height / (Math.abs(data.getMaxY()) + Math.abs(data.getMinY()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@ public class ChartData {
|
||||||
|
|
||||||
private HashMap<Integer,String> xStrings;
|
private HashMap<Integer,String> xStrings;
|
||||||
private HashMap<Integer,String> yStrings;
|
private HashMap<Integer,String> yStrings;
|
||||||
private int maxx;
|
private int maxX;
|
||||||
private int minx;
|
private int minX;
|
||||||
private int maxy;
|
private int maxY;
|
||||||
private int miny;
|
private int minY;
|
||||||
|
|
||||||
private ArrayList<Point> points;
|
private ArrayList<Point> points;
|
||||||
|
|
||||||
|
|
@ -61,37 +61,37 @@ public class ChartData {
|
||||||
setMaxMin(x, y);
|
setMaxMin(x, y);
|
||||||
}
|
}
|
||||||
public void addPoint(int y){
|
public void addPoint(int y){
|
||||||
points.add( new Point( maxx, y));
|
points.add( new Point(maxX, y));
|
||||||
maxx++;
|
maxX++;
|
||||||
setMaxMin(maxx, y);
|
setMaxMin(maxX, y);
|
||||||
}
|
}
|
||||||
public void addPoint(String x, int y){
|
public void addPoint(String x, int y){
|
||||||
xStrings.put(maxx, x);
|
xStrings.put(maxX, x);
|
||||||
points.add( new Point( maxx, y));
|
points.add( new Point(maxX, y));
|
||||||
maxx++;
|
maxX++;
|
||||||
setMaxMin(maxx, y);
|
setMaxMin(maxX, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setMaxMin(int x, int y){
|
private void setMaxMin(int x, int y){
|
||||||
if( x > maxx ) maxx = x;
|
if( x > maxX) maxX = x;
|
||||||
else if( x < minx ) minx = x;
|
if( x < minX) minX = x;
|
||||||
|
|
||||||
if( y > maxy ) maxx = y;
|
if( y > maxY) maxY = y;
|
||||||
else if( y < miny ) minx = y;
|
if( y < minY) minY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxX(){
|
public int getMaxX(){
|
||||||
return maxx;
|
return maxX;
|
||||||
}
|
}
|
||||||
public int getMinX(){
|
public int getMinX(){
|
||||||
return minx;
|
return minX;
|
||||||
}
|
}
|
||||||
public int getMaxY(){
|
public int getMaxY(){
|
||||||
return maxy;
|
return maxY;
|
||||||
}
|
}
|
||||||
public int getMinY(){
|
public int getMinY(){
|
||||||
return miny;
|
return minY;
|
||||||
}
|
}
|
||||||
public String getXString(int x){
|
public String getXString(int x){
|
||||||
return xStrings.get(x);
|
return xStrings.get(x);
|
||||||
|
|
|
||||||
75
src/zutil/chart/LineAxis.java
Executable file
75
src/zutil/chart/LineAxis.java
Executable file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package zutil.chart;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class LineAxis extends AbstractChart{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Rectangle drawAxis(Graphics2D g2, Rectangle bound){
|
||||||
|
if( data == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
width = bound.width;
|
||||||
|
height = bound.height;
|
||||||
|
chartBound = new Rectangle();
|
||||||
|
int stepLength = 7;
|
||||||
|
|
||||||
|
// **********************************
|
||||||
|
// Calculate Font sizes
|
||||||
|
// **********************************
|
||||||
|
|
||||||
|
FontMetrics metric = g2.getFontMetrics();
|
||||||
|
int fontHeight = metric.getHeight();
|
||||||
|
int fontXWidth = 0;
|
||||||
|
int fontYWidth = 0;
|
||||||
|
for( Point p : data.getPoints() ){
|
||||||
|
int length;
|
||||||
|
String tmp = data.getXString( p.x );
|
||||||
|
if( tmp != null ) length = metric.stringWidth( tmp );
|
||||||
|
else length = metric.stringWidth( ""+p.x );
|
||||||
|
fontXWidth = Math.max(length, fontXWidth);
|
||||||
|
|
||||||
|
tmp = data.getXString( p.y );
|
||||||
|
if( tmp != null ) length = metric.stringWidth( tmp );
|
||||||
|
else length = metric.stringWidth( ""+p.y );
|
||||||
|
fontYWidth = Math.max(length, fontYWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate origo
|
||||||
|
|
||||||
|
Point origo = new Point(
|
||||||
|
PADDING + fontYWidth + stepLength,
|
||||||
|
height - PADDING - fontHeight - stepLength );
|
||||||
|
chartBound.x = (int) (origo.getX() + 1);
|
||||||
|
chartBound.y = PADDING;
|
||||||
|
chartBound.width = width - chartBound.x - PADDING;
|
||||||
|
chartBound.height = (int) (origo.getY() - PADDING - 1);
|
||||||
|
|
||||||
|
// **********************************
|
||||||
|
// Draw
|
||||||
|
// **********************************
|
||||||
|
|
||||||
|
g2.setColor(Color.LIGHT_GRAY);
|
||||||
|
g2.setStroke(new BasicStroke(1.5f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
|
||||||
|
|
||||||
|
// Y Axis
|
||||||
|
g2.draw( new Line2D.Double( origo.getX(), PADDING, origo.getX(), origo.getY() ));
|
||||||
|
// X Axis
|
||||||
|
g2.draw( new Line2D.Double( origo.getX(), origo.getY(), width-PADDING, origo.getY() ));
|
||||||
|
// Y Axis steps and labels
|
||||||
|
|
||||||
|
// X Axis steps and labels
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
/*
|
||||||
|
g2.setColor(Color.red);
|
||||||
|
g2.drawRect(bound.x, bound.y, bound.width, bound.height);
|
||||||
|
*/
|
||||||
|
return chartBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -27,36 +27,36 @@ package zutil.chart;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.Line2D;
|
import java.awt.geom.Line2D;
|
||||||
|
|
||||||
public class LineChart extends AbstractChart{
|
public class LineChart extends LineAxis{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void drawChart(Graphics2D g2, Rectangle bound) {
|
protected void drawChart(Graphics2D g2, Rectangle bound) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
drawLine(g2, 50, 50,100,150);
|
|
||||||
drawLine(g2, 100,150,150,100);
|
|
||||||
drawLine(g2, 150,100,200,300);
|
|
||||||
drawLine(g2, 200,300,250,40);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawLine(Graphics2D g2, float x1, float y1, float x2, float y2){
|
|
||||||
// Shadow
|
|
||||||
g2.setPaint(new Color(220,220,220));
|
|
||||||
g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
|
||||||
g2.draw( new Line2D.Float(x1, y1+2, x2, y2+2));
|
|
||||||
// Smoth shadow
|
|
||||||
g2.setPaint(new Color(230,230,230));
|
|
||||||
g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
|
||||||
g2.draw( new Line2D.Float(x1+1, y1+3, x2-1, y2+3));
|
|
||||||
|
|
||||||
// Line border
|
|
||||||
g2.setPaint(new Color(255,187,187));
|
|
||||||
g2.setStroke(new BasicStroke(4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
|
||||||
g2.draw( new Line2D.Float(x1, y1, x2, y2));
|
|
||||||
|
|
||||||
// Line
|
|
||||||
g2.setPaint(new Color(237,28,36));
|
g2.setPaint(new Color(237,28,36));
|
||||||
g2.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
g2.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
||||||
g2.draw( new Line2D.Float(x1, y1, x2, y2));
|
|
||||||
|
// Calculate position
|
||||||
|
|
||||||
|
double xScale = getXScale(data, bound);
|
||||||
|
double yScale = getYScale(data, bound);
|
||||||
|
|
||||||
|
// Draw lines
|
||||||
|
|
||||||
|
Point prevP = null;
|
||||||
|
for(Point p : data.getPoints()){
|
||||||
|
if (prevP != null)
|
||||||
|
drawLine(g2, bound, xScale, yScale, prevP.x, prevP.y, p.x, p.y);
|
||||||
|
prevP = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawLine(Graphics2D g2, Rectangle bound, double xScale, double yScale,
|
||||||
|
double x1, double y1, double x2, double y2){
|
||||||
|
// Line
|
||||||
|
g2.draw(new Line2D.Double(
|
||||||
|
getXCoordinate(x1, xScale, bound),
|
||||||
|
getYCoordinate(y1, yScale, bound),
|
||||||
|
getXCoordinate(x2, xScale, bound),
|
||||||
|
getYCoordinate(y2, yScale, bound)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,21 +41,22 @@ public class ChartTest extends JFrame{
|
||||||
|
|
||||||
public ChartTest(){
|
public ChartTest(){
|
||||||
ChartData data = new ChartData();
|
ChartData data = new ChartData();
|
||||||
|
data.addPoint(0,0);
|
||||||
data.addPoint(1,1);
|
data.addPoint(1,1);
|
||||||
data.addPoint(2,1);
|
data.addPoint(2,2);
|
||||||
data.addPoint(3,1);
|
data.addPoint(3,3);
|
||||||
data.addPoint(4,1);
|
data.addPoint(4,4);
|
||||||
data.addPoint(5,1);
|
data.addPoint(5,5);
|
||||||
data.addPoint(6,1);
|
data.addPoint(6,6);
|
||||||
data.addPoint(7,1);
|
data.addPoint(7,7);
|
||||||
data.addPoint(8,1);
|
data.addPoint(8,8);
|
||||||
|
|
||||||
LineChart chart = new LineChart();
|
LineChart chart = new LineChart();
|
||||||
chart.setChartData( data );
|
chart.setChartData( data );
|
||||||
this.add( chart );
|
add( chart );
|
||||||
|
|
||||||
this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
|
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
|
||||||
this.setSize(600, 400);
|
setSize(600, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue