some look and feel customisation of jfree chart

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
alsw-2000
Posts: 16
Joined: Thu May 22, 2003 12:53 pm

some look and feel customisation of jfree chart

Post by alsw-2000 » Mon Jan 26, 2004 12:44 pm

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

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Mon Jan 26, 2004 2:35 pm

(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:

Code: Select all

renderer.setSeriesPaint(0, Color.RED);
renderer.setSeriesPaint(1, Color.BLACK);
renderer.setSeriesPaint(2, Color.DARK_GRAY);
(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:

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;
    }
}
...and a demo application:

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

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Ayilay
Posts: 2
Joined: Mon Sep 10, 2018 8:16 pm
antibot: No, of course not.

Aligning Range GridLines with secondary Range Axis

Post by Ayilay » Mon Sep 10, 2018 8:25 pm

david.gilbert wrote:
Mon Jan 26, 2004 2:35 pm
(2) At present, grid lines are only drawn for the ticks on the primary axis.
I really need this functionality in my current project :lol:

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

Locked