NumberAxis label at wrong place when using label angle

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
uvoigt
Posts: 168
Joined: Mon Aug 23, 2004 10:50 am
Location: Germany

NumberAxis label at wrong place when using label angle

Post by uvoigt » Tue Jul 01, 2014 2:31 pm

The label of a NumberAxis is rendered at the wrong place when setting the label angle and getAxisLabelLocation() != MIDDLE.

Please try the following test program which rotates the label of a NumberAxis and changes the location after one complete turn.

Code: Select all

/* -------------------
 * LineChartDemo1.java
 * -------------------
 * (C) Copyright 2002-2011, by Object Refinery Limited.
 *
 */

package demo;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLabelLocation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.HorizontalAlignment;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;

/**
 * A simple demonstration application showing how to create a line chart using data from a
 * {@link CategoryDataset}.
 */
public class LineChartDemo1
    extends ApplicationFrame
{

    /**
     * Creates a new demo.
     * 
     * @param title the frame title.
     */
    public LineChartDemo1(String title)
    {
        super(title);
        JPanel chartPanel = createDemoPanel();
        chartPanel.setPreferredSize(new Dimension(500, 270));
        setContentPane(chartPanel);
    }

    /**
     * Creates a sample dataset.
     * 
     * @return The dataset.
     */
    private static CategoryDataset createDataset()
    {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        dataset.addValue(212, "Classes", "JDK 1.0");
        dataset.addValue(504, "Classes", "JDK 1.1");
        dataset.addValue(1520, "Classes", "JDK 1.2");
        dataset.addValue(1842, "Classes", "JDK 1.3");
        dataset.addValue(2991, "Classes", "JDK 1.4");
        dataset.addValue(3500, "Classes", "JDK 1.5");
        return dataset;
    }

    /**
     * Creates a sample chart.
     * 
     * @param dataset a dataset.
     * @return The chart.
     */
    private static JFreeChart createChart(CategoryDataset dataset)
    {

        // create the chart...
        JFreeChart chart = ChartFactory.createLineChart("Java Standard Class Library", // chart
                                                                                       // title
            null, // domain axis label
            "Class Count", // range axis label
            dataset, // data
            PlotOrientation.VERTICAL, // orientation
            false, // include legend
            true, // tooltips
            false // urls
            );

        chart.addSubtitle(new TextTitle("Number of Classes By Release"));
        TextTitle source = new TextTitle("Source: Java In A Nutshell (5th Edition) " + "by David Flanagan (O'Reilly)");
        source.setFont(new Font("SansSerif", Font.PLAIN, 10));
        source.setPosition(RectangleEdge.BOTTOM);
        source.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        chart.addSubtitle(source);

        CategoryPlot plot = (CategoryPlot)chart.getPlot();
        plot.setRangePannable(true);
        plot.setRangeGridlinesVisible(false);
        URL imageURL = LineChartDemo1.class.getClassLoader().getResource("OnBridge11small.png");
        if (imageURL != null)
        {
            ImageIcon temp = new ImageIcon(imageURL);
            // use ImageIcon because it waits for the image to load...
            chart.setBackgroundImage(temp.getImage());
            plot.setBackgroundPaint(null);
        }
        // customise the range axis...
        final NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        // ===============================================================================
        // Rotate the axis label
        //
        new Timer(5, new ActionListener()
        {
            private double startAngle = 0.0d;

            @Override
            public void actionPerformed(ActionEvent e)
            {
                this.startAngle += 1;
                if (this.startAngle > 359)
                {
                    // reset to 0°
                    this.startAngle = 0;

                    // switch the label location
                    if (rangeAxis.getLabelLocation() == AxisLabelLocation.HIGH_END)
                    {
                        rangeAxis.setLabelLocation(AxisLabelLocation.MIDDLE);
                    }
                    else if (rangeAxis.getLabelLocation() == AxisLabelLocation.MIDDLE)
                    {
                        rangeAxis.setLabelLocation(AxisLabelLocation.LOW_END);
                    }
                    else if (rangeAxis.getLabelLocation() == AxisLabelLocation.LOW_END)
                    {
                        rangeAxis.setLabelLocation(AxisLabelLocation.HIGH_END);
                    }
                }
                rangeAxis.setLabelAngle(Math.toRadians(this.startAngle));
            }
        }).start();

        // ===============================================================================

        ChartUtilities.applyCurrentTheme(chart);

        // customise the renderer...
        LineAndShapeRenderer renderer = (LineAndShapeRenderer)plot.getRenderer();
        renderer.setBaseShapesVisible(true);
        renderer.setDrawOutlines(true);
        renderer.setUseFillPaint(true);
        renderer.setBaseFillPaint(Color.white);
        renderer.setSeriesStroke(0, new BasicStroke(3.0f));
        renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0f));
        renderer.setSeriesShape(0, new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0));
        return chart;
    }

    /**
     * Creates a panel for the demo (used by SuperDemo.java).
     * 
     * @return A panel.
     */
    public static JPanel createDemoPanel()
    {
        JFreeChart chart = createChart(createDataset());
        ChartPanel panel = new ChartPanel(chart);
        panel.setMouseWheelEnabled(true);
        return panel;
    }

    /**
     * Starting point for the demonstration application.
     * 
     * @param args ignored.
     */
    public static void main(String[] args)
    {
        LineChartDemo1 demo = new LineChartDemo1("JFreeChart: LineChartDemo1.java");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

}

uvoigt
Posts: 168
Joined: Mon Aug 23, 2004 10:50 am
Location: Germany

Re: NumberAxis label at wrong place when using label angle

Post by uvoigt » Tue Jul 01, 2014 2:44 pm


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

Re: NumberAxis label at wrong place when using label angle

Post by david.gilbert » Tue Jul 01, 2014 2:53 pm

Thanks, and nice test case. I did not think about label rotation when I provided the options to put the labels at the top or bottom of the axis (or if I did think about it, I didn't think about it very well). I'm not sure what the "correct" behavior should be here...
David Gilbert
JFreeChart Project Leader

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

uvoigt
Posts: 168
Joined: Mon Aug 23, 2004 10:50 am
Location: Germany

Re: NumberAxis label at wrong place when using label angle

Post by uvoigt » Tue Jul 01, 2014 3:02 pm

I would like to have a fully visible rotated label that is placed uppermost (HIGH_END) or lowermost (LOW_END) :P

Locked