My user want to change the chart library to jfree chart, but I can't solve some of his requirements about the look and feel of the chart, is there anyone can help?
1)
he want to use Red, Black and Dark grey as first 3 colours for the charts traces of the XYPlot, is there any function in the StandardXYItemRenderer class can do that?
2)
I find that the range gridlines in a double axis chart only align to the primary axis's tick, is there any method to set it align to both primary and secondary's tick label?
3)
is there any function to change the range gridline's color and style?
4)
is there any method to put the y-axis's label at the top of the axis not beside it?
Andy
some look and feel customisation of jfree chart
-
- JFreeChart Project Leader
- Posts: 11734
- Joined: Fri Mar 14, 2003 10:29 am
- antibot: No, of course not.
- Contact:
(1) The default paint sequence is generated by the ChartColor class, so if you want to change the settings globally for all charts that you create, modify this class and recompile JFreeChart. But if you just want to change one particular chart, use the chart's renderer:
(2) At present, grid lines are only drawn for the ticks on the primary axis.
(3) In the XYPlot class, you can use the methods setDomainGridlinePaint(), setDomainGridlineStroke(), setRangeGridlinePaint() and setRangeGridlineStroke().
(4) This isn't supported, because I haven't worked out a good scheme for ensuring the label at the top of the axis doesn't conflict with the chart title. But here is some code I sent to another developer that will get you started if you want to experiment with this yourself:
...and a demo application:
Code: Select all
renderer.setSeriesPaint(0, Color.RED);
renderer.setSeriesPaint(1, Color.BLACK);
renderer.setSeriesPaint(2, Color.DARK_GRAY);
(3) In the XYPlot class, you can use the methods setDomainGridlinePaint(), setDomainGridlineStroke(), setRangeGridlinePaint() and setRangeGridlineStroke().
(4) This isn't supported, because I haven't worked out a good scheme for ensuring the label at the top of the axis doesn't conflict with the chart title. But here is some code I sent to another developer that will get you started if you want to experiment with this yourself:
Code: Select all
package org.jfree.chart.axis;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import org.jfree.text.TextBlock;
import org.jfree.text.TextBlockAnchor;
import org.jfree.ui.RectangleEdge;
/**
* @author sony
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class ExtendedNumberAxis extends NumberAxis {
/** A special label. */
private TextBlock specialLabel;
/**
* Creates a new axis.
*
* @param specialLabel a label.
*/
public ExtendedNumberAxis(TextBlock specialLabel) {
super(null);
this.specialLabel = specialLabel;
}
public TextBlock getSpecialLabel() {
return this.specialLabel;
}
public void setSpecialLabel(TextBlock label) {
this.specialLabel = label;
}
public AxisState draw(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
AxisState result = super.draw(g2, cursor, plotArea, dataArea, edge);
// now draw the special label...
if (this.specialLabel == null) {
return result;
}
float x = 0.0f;
float y = 0.0f;
Dimension d = this.specialLabel.calculateDimensions(g2);
if (edge == RectangleEdge.TOP) {
x = (float) dataArea.getMaxX();
y = (float) cursor;
this.specialLabel.draw(g2, x, y, TextBlockAnchor.BOTTOM_LEFT);
result.setCursor(Math.min(cursor - d.height, result.getCursor()));
}
else if (edge == RectangleEdge.BOTTOM) {
x = (float) dataArea.getMaxX();
y = (float) (cursor);
this.specialLabel.draw(g2, x, y, TextBlockAnchor.TOP_LEFT);
result.setCursor(Math.max(cursor + d.height, result.getCursor()));
}
else if (edge == RectangleEdge.LEFT) {
x = (float) (cursor);
y = (float) dataArea.getMinY();
this.specialLabel.draw(g2, x, y, TextBlockAnchor.BOTTOM_RIGHT);
result.setCursor(Math.min(cursor - d.width, result.getCursor()));
}
else if (edge == RectangleEdge.RIGHT) {
x = (float) (cursor);
y = (float) dataArea.getMinY();
this.specialLabel.draw(g2, x, y, TextBlockAnchor.BOTTOM_LEFT);
result.setCursor(Math.max(cursor + d.width, result.getCursor()));
}
return result;
}
}
Code: Select all
package org.jfree.chart.demo;
import java.awt.Color;
import java.awt.Font;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.Spacer;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.ExtendedNumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.StandardXYItemRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.XYDataset;
import org.jfree.data.time.Minute;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.text.TextBlock;
import org.jfree.text.TextLine;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
/**
* An example of....
*
* @author David Gilbert
*/
public class MultipleAxisDemo4 extends ApplicationFrame {
/**
* A demonstration application showing how to create a time series chart with muliple axes.
*
* @param title the frame title.
*/
public MultipleAxisDemo4(String title) {
super(title);
JFreeChart chart = createChart();
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(600, 270));
chartPanel.setHorizontalZoom(true);
chartPanel.setVerticalZoom(true);
setContentPane(chartPanel);
}
/**
* Creates the demo chart.
*
* @return The chart.
*/
private JFreeChart createChart() {
XYDataset dataset1 = createDataset("Series 1", 100.0, new Minute(), 200);
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"Multiple Axis Demo 1",
"Time of Day",
"Primary Range Axis",
dataset1,
true,
true,
false
);
chart.setBackgroundPaint(Color.white);
chart.addSubtitle(new TextTitle("Four datasets and four range axes."));
XYPlot plot = chart.getXYPlot();
Font f = new Font("SansSerif", Font.PLAIN, 10);
TextBlock label1 = new TextBlock();
label1.addLine(new TextLine("Range", f));
label1.addLine(new TextLine("Axis 1", f));
ExtendedNumberAxis axis1 = new ExtendedNumberAxis(label1);
plot.setRangeAxis(axis1);
plot.setOrientation(PlotOrientation.VERTICAL);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
StandardXYItemRenderer renderer = (StandardXYItemRenderer) plot.getRenderer();
renderer.setPaint(Color.black);
// AXIS 2
TextBlock label2 = new TextBlock();
label2.addLine(new TextLine("Range", f));
label2.addLine(new TextLine("Axis 2", f));
ExtendedNumberAxis axis2 = new ExtendedNumberAxis(label2);
axis2.setAutoRangeIncludesZero(false);
axis2.setLabelPaint(Color.red);
axis2.setTickLabelPaint(Color.red);
plot.setSecondaryRangeAxis(0, axis2);
plot.setSecondaryRangeAxisLocation(0, AxisLocation.BOTTOM_OR_LEFT);
XYDataset dataset2 = createDataset("Series 2", 1000.0, new Minute(), 170);
plot.setSecondaryDataset(0, dataset2);
plot.mapSecondaryDatasetToRangeAxis(0, new Integer(0));
plot.setSecondaryRenderer(0, new StandardXYItemRenderer());
plot.getSecondaryRenderer(0).setSeriesPaint(0, Color.red);
// AXIS 3
TextBlock label3 = new TextBlock();
label3.addLine(new TextLine("Range", f));
label3.addLine(new TextLine("Axis 3", f));
ExtendedNumberAxis axis3 = new ExtendedNumberAxis(label3);
axis3.setLabelPaint(Color.blue);
axis3.setTickLabelPaint(Color.blue);
plot.setSecondaryRangeAxis(1, axis3);
XYDataset dataset3 = createDataset("Series 3", 10000.0, new Minute(), 170);
plot.setSecondaryDataset(1, dataset3);
plot.mapSecondaryDatasetToRangeAxis(1, new Integer(1));
plot.setSecondaryRenderer(1, new StandardXYItemRenderer());
plot.getSecondaryRenderer(1).setSeriesPaint(0, Color.blue);
// AXIS 4
TextBlock label4 = new TextBlock();
label4.addLine(new TextLine("Range", f));
label4.addLine(new TextLine("Axis 4", f));
ExtendedNumberAxis axis4 = new ExtendedNumberAxis(label4);
axis4.setLabelPaint(Color.green);
axis4.setTickLabelPaint(Color.green);
plot.setSecondaryRangeAxis(2, axis4);
XYDataset dataset4 = createDataset("Series 4", 25.0, new Minute(), 200);
plot.setSecondaryDataset(2, dataset4);
plot.mapSecondaryDatasetToRangeAxis(2, new Integer(2));
plot.setSecondaryRenderer(2, new StandardXYItemRenderer());
plot.getSecondaryRenderer(2).setSeriesPaint(0, Color.green);
return chart;
}
// ****************************************************************************
// * JFREECHART DEVELOPER GUIDE *
// * The JFreeChart Developer Guide, written by David Gilbert, is available *
// * to purchase from Object Refinery Limited: *
// * *
// * http://www.object-refinery.com/jfreechart/guide.html *
// * *
// * Sales are used to provide funding for the JFreeChart project - please *
// * support us so that we can continue developing free software. * *
// ****************************************************************************
/**
* Creates a sample dataset.
*
* @param name the dataset name.
* @param base the starting value.
* @param start the starting period.
* @param count the number of values to generate.
*
* @return The dataset.
*/
private XYDataset createDataset(String name, double base, RegularTimePeriod start, int count) {
TimeSeries series = new TimeSeries(name, start.getClass());
RegularTimePeriod period = start;
double value = base;
for (int i = 0; i < count; i++) {
series.add(period, value);
period = period.next();
value = value * (1 + (Math.random() - 0.495) / 10.0);
}
TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(series);
return dataset;
}
/**
* Starting point for the demonstration application.
*
* @param args ignored.
*/
public static void main(String[] args) {
MultipleAxisDemo4 demo = new MultipleAxisDemo4("Multiple Axis Demo 4");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
David Gilbert
JFreeChart Project Leader
Read my blog
Support JFree via the Github sponsorship program
JFreeChart Project Leader


Aligning Range GridLines with secondary Range Axis
I really need this functionality in my current projectdavid.gilbert wrote: ↑Mon Jan 26, 2004 2:35 pm(2) At present, grid lines are only drawn for the ticks on the primary axis.

Say I want to implement this functionality myself via extending some of the API classes. Do you have any advice as to what classes I should be looking at?
Thanks in advance