JFreeChart Fixed range axis ticks

I am trying to generate a line chart but I cannot figure out how to

a) setup the range axis with fixed ticks for 0.001, 0.01, 0.1, 1, 10 and 100

b) display only those ticks in the graph

c) Custom label those ticks (which can only be addressed after a and b).

I am trying to use a SymbolAxis but I cannot get it working.

This is what I am after:

enter image description here


Solution 1:

After some experimentation. Following example

enter image description here

public static void main(String[] args) {
    //setting up my ticks
    final TickUnits standardUnits = new TickUnits();
    standardUnits.add(new NumberTickUnit(0.001));
    standardUnits.add(new NumberTickUnit(0.01));
    standardUnits.add(new NumberTickUnit(0.1));
    standardUnits.add(new NumberTickUnit(1));
    standardUnits.add(new NumberTickUnit(10));
    standardUnits.add(new NumberTickUnit(100));

    //data
    XYSeries series = new XYSeries("Series");
    series.add(0, 130);
    series.add(1, 0.35);
    series.add(2, 0.021);
    series.add(3, 0.0042);
    series.add(4, 0.002);
    series.add(5, 0.003);
    series.add(6, 10130);
    
    NumberAxis xAxis = new NumberAxis("X");
    xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
    LogAxis yAxis = new LogAxis("Y");
    yAxis.setBase(10);      
    yAxis.setNumberFormatOverride(new DecimalFormat());
    yAxis.setRange(0.001, 100);
    yAxis.setStandardTickUnits(standardUnits); // NumberAxis.createIntegerTickUnits());
    XYPlot plot = new XYPlot(new XYSeriesCollection(series), xAxis, yAxis, new XYLineAndShapeRenderer(true, false));
    JFreeChart chart = new JFreeChart("Chart", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
    JFrame frame = new JFrame("LogAxis Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setContentPane(new ChartPanel(chart));
    frame.pack();
    frame.setVisible(true);
}

Solution 2:

This approach illustrates using a LogAxis with integer tick units, as suggested here. The particular set of tick units shown is sometimes warranted, but a more general solution is seen in the variation below; it relies on the TickUnitSource created by NumberAxis:

yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

Moreover,

  • As discussed here, absent a ChartFactory, a suitable ChartTheme "establishes coherent defaults for elements that affect geometry, such as font metrics and axis offsets."

  • As mentioned here, it is essential to construct and manipulate Swing GUI objects only on the event dispatch thread.

  • As shown here, NumberFormat.getNumberInstance() is an alternative to DecimalFormat.

LogTest image

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.text.NumberFormat;
import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class LogTest {

    /**
     * @see https://stackoverflow.com/a/70648615/230513
     * @see https://stackoverflow.com/a/10353270/230513
     */
    private void display() {
        XYSeries series = new XYSeries("Series");
        series.add(0, 130);
        series.add(1, 0.35);
        series.add(2, 0.021);
        series.add(3, 0.0042);
        series.add(4, 0.002);
        series.add(5, 0.003);
        series.add(6, 10130);

        NumberAxis xAxis = new NumberAxis("X");
        xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        LogAxis yAxis = new LogAxis("Y");
        yAxis.setBase(10);
        yAxis.setNumberFormatOverride(NumberFormat.getNumberInstance());
        yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        XYPlot plot = new XYPlot(new XYSeriesCollection(series),
            xAxis, yAxis, new XYLineAndShapeRenderer(true, false));
        JFreeChart chart = new JFreeChart("Chart",
            JFreeChart.DEFAULT_TITLE_FONT, plot, false);
        StandardChartTheme theme = new StandardChartTheme("Custom");
        theme.setPlotBackgroundPaint(Color.WHITE);
        theme.setChartBackgroundPaint(new GradientPaint(
            0, 0, Color.WHITE, 0, 480, new Color(0xB8C8E0)));
        theme.apply(chart);

        JFrame f = new JFrame("LogAxis Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new ChartPanel(chart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }
        });
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new LogTest()::display);
    }
}