Help with Repeating Domain axis labels

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Alfred63
Posts: 22
Joined: Mon Jun 21, 2004 9:38 pm

Help with Repeating Domain axis labels

Post by Alfred63 » Mon Oct 30, 2006 6:03 pm

I'm having a bit of trouble finding the magic bullet for keeping the domain axis from repeating labels, if this is indeed possible. Anyone have any ideas?

Here is what I'm using for code:

Code: Select all

public abstract class AbstractMopChart extends JPanel implements DataManager2Listener
{
    private TimeSeries avgSeries;
    private TimeSeries minSeries;
    private TimeSeries maxSeries;
    private TimeSeriesCollection dataset = new TimeSeriesCollection ();
    private Class      timeUnit = Hour.class;
    ChartPanel         chartPanel;
    JFreeChart         chart;
    private int        keyLevel;
    private int        calendarUnit;
    private DateAxis   domain; 

    private StandardXYItemRenderer renderer;
    
    private LegendTitle    legend;
    private JPopupMenu     popup;
    private AbstractAction actionShowLegend = new ActionShowLegend ();
    private AbstractAction actionHideLegend = new ActionHideLegend ();
    

    public AbstractMopChart ()
    {
        super (new BorderLayout ());
        
        setBackground (MopMainPanel.MopPanelColor);

        actionShowLegend = new ActionShowLegend ();
        actionHideLegend = new ActionHideLegend ();

        createSeries (timeUnit);
      
        domain = new DateAxis ("Time");
        
        domain.setDateFormatOverride (new SimpleDateFormat ("H"));
        domain.setTickLabelFont (new Font ("SansSerif", Font.PLAIN, 10));
        domain.setLabelFont (new Font ("SansSerif", Font.PLAIN, 12));
        
        renderer = new StandardXYItemRenderer (StandardXYItemRenderer.SHAPES_AND_LINES);
        
        renderer.setSeriesPaint (0, Color.GREEN);
        renderer.setSeriesPaint (1, Color.BLUE);
        renderer.setSeriesPaint (2, Color.RED);
        
        XYToolTipGenerator generator = new StandardXYToolTipGenerator (
                "<html><center>" + " Value={2} " + "<br> Time={1} " + "</center></html>", 
                new SimpleDateFormat ("hh:mm a  MMM-d-yyyy"),
                new DecimalFormat ("#,##0.00"));
        renderer.setToolTipGenerator (generator);
        
        renderer.setStroke(new BasicStroke(2f, 
                BasicStroke.CAP_BUTT, 
                BasicStroke.JOIN_BEVEL));
        
        Arc2D circle = new Arc2D.Float(-1f,-1f,3f,3f,0f,360f,Arc2D.OPEN);
        renderer.setShape(circle);
        
        ValueAxis range = createRangeAxis();
        
        XYPlot plot = new XYPlot(dataset, domain, range, renderer);
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(3.0, 3.0, 3.0, 3.0));
        plot.setForegroundAlpha(0.7f);
        
        domain.setAutoRange(true);
        domain.setTickLabelsVisible(true);
        chart = new JFreeChart("Generic",
                new Font("SansSerif", Font.BOLD, 13),
                plot,
                true);
        
        chart.setBorderPaint (Color.black);
        chart.setBorderVisible (true);
        chart.setBackgroundPaint(Color.white);
        
        chartPanel = new ChartPanel (chart, 
                false,      // Show properties menu
                true,       // Show save 
                true,       // Show print 
                false,      // Show zoom control
                true);      // Show tooltips
        
        
        legend = chart.getLegend ();
            
        actionHideLegend.setEnabled (true);
        actionShowLegend.setEnabled (false);
        
        addToPopupMenu (chartPanel.getPopupMenu ());
        
    }
Thanks for your help!

-Dennis Klotz[/code]

Alfred63
Posts: 22
Joined: Mon Jun 21, 2004 9:38 pm

Post by Alfred63 » Mon Oct 30, 2006 7:11 pm

Perhaps it would help if I try explaining the problem in a different way.

The problem I'm trying to correct is when I have a timeline on the X axis that has simple hour tick marks. When the range is small I see an X axis like the following:


1 1 1 2 2 2 3 3 3 4 4 4


But there is only one actual data point for each beginning hour mark. Does that make sense?

I am hoping there is a way to say domainaxis.setNoRepeatingTickLabels () or something close.

Your help is greatly appreciated.

-Dennis

Carl Manaster
Posts: 35
Joined: Tue Mar 28, 2006 1:10 am
Location: La Jolla
Contact:

A possible hint

Post by Carl Manaster » Mon Oct 30, 2006 7:29 pm

I would guess that instead of 111222333444, what it's trying to produce is, eg:
1.0 1.3 1.6, etc.

So the values aren't actually all the same; it just looks that way because of the number format. I don't have the API in front of me, but I'll bet there's a call to tell it what the spacing between tick labels should be; set it to 1.0 and you're good to go.

Alfred63
Posts: 22
Joined: Mon Jun 21, 2004 9:38 pm

Re: A possible hint

Post by Alfred63 » Mon Oct 30, 2006 11:30 pm

Carl Manaster wrote:I would guess that instead of 111222333444, what it's trying to produce is, eg:
1.0 1.3 1.6, etc.

So the values aren't actually all the same; it just looks that way because of the number format. I don't have the API in front of me, but I'll bet there's a call to tell it what the spacing between tick labels should be; set it to 1.0 and you're good to go.
Thanks Carl.

Here is what I ended up doing to fix the problem, however it has its own set of added problems. For example, label overlap.

Code: Select all

    public void setChartTimeGranularity (Class timeUnit)
    {
        String label;
        XYPlot plot = chart.getXYPlot ();
        DateAxis axis = (DateAxis)plot.getDomainAxis ();
        
        if (timeUnit == Day.class)
        {
            calendarUnit = Calendar.DAY_OF_MONTH;
            axis.setTickUnit (new DateTickUnit (DateTickUnit.DAY, 1));
            axis.setDateFormatOverride (new SimpleDateFormat ("MMM/d"));
            label = "Time (Month/Day)";
        }
        else if (timeUnit == Hour.class)
        {
            calendarUnit = Calendar.HOUR_OF_DAY;
            axis.setTickUnit (new DateTickUnit (DateTickUnit.HOUR, 1));
            axis.setDateFormatOverride (new SimpleDateFormat ("H"));
            axis.setAutoTickUnitSelection (true);
            label = "Time (Hours)";
        }
        else 
        {
            calendarUnit = Calendar.MINUTE;
            axis.setTickUnit (new DateTickUnit (DateTickUnit.MINUTE, 1));
            axis.setDateFormatOverride (new SimpleDateFormat ("m"));
            axis.setAutoTickUnitSelection (true);
            label = "Time (Minutes)";
        }
        this.timeUnit = timeUnit;
        axis.setLabel (label);
    }
Thanks again for your help.

-Dennis

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 » Tue Oct 31, 2006 3:21 pm

It sounds like you'd be better to use the setStandardTickUnits() method to define the tick units that you want to be available to the DateAxis. That way, you can control the formatting, but still allow the axis to choose an appropriate tick size to avoid overlapping labels.
David Gilbert
JFreeChart Project Leader

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

Alfred63
Posts: 22
Joined: Mon Jun 21, 2004 9:38 pm

Post by Alfred63 » Tue Oct 31, 2006 3:29 pm

Thanks David!

I'm going to look into that right now.

Hey just in case nobody has ever told you... Your product is truly the best out there and the level of professionalism in the code and documentation is better than I see in most commercial products. I think its about time for me to buy another document. :) (I'll do it when 1.03 is out)

Keep up the good work.

-Dennis

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 » Tue Oct 31, 2006 3:50 pm

Alfred63 wrote:Hey just in case nobody has ever told you... Your product is truly the best out there and the level of professionalism in the code and documentation is better than I see in most commercial products. I think its about time for me to buy another document. :) (I'll do it when 1.03 is out)
Thanks! I appreciate your comments. I plan to carry on improving JFreeChart for a long time yet - there's plenty to do, of course!
David Gilbert
JFreeChart Project Leader

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

Alfred63
Posts: 22
Joined: Mon Jun 21, 2004 9:38 pm

Post by Alfred63 » Tue Oct 31, 2006 4:22 pm

David,

Is this what you are thinking of?

Code: Select all

        final DateAxis axis = (DateAxis) plot.getDomainAxis();
        final TickUnits standardUnits = new TickUnits();
        standardUnits.add(
            new DateTickUnit(DateTickUnit.DAY, 1, new SimpleDateFormat("MMM dd ''yy"))
        );
        standardUnits.add(
                new DateTickUnit(DateTickUnit.DAY, 7, new SimpleDateFormat("MMM dd ''yy"))
        );
        standardUnits.add(
                new DateTickUnit(DateTickUnit.MONTH, 1, new SimpleDateFormat("MMM ''yy"))
        );
        axis.setStandardTickUnits(standardUnits);
        
Thanks.

-Dennis

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 » Tue Oct 31, 2006 4:28 pm

Yes. This lets you control the smallest tick unit for the axis (here you'll get nothing less than one day) but also leaves the option for the axis to select a larger tick unit when there would otherwise be overlapping labels. And you get to specify the format that you want for each size.
David Gilbert
JFreeChart Project Leader

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

Alfred63
Posts: 22
Joined: Mon Jun 21, 2004 9:38 pm

Post by Alfred63 » Tue Oct 31, 2006 9:42 pm

david.gilbert wrote:Yes. This lets you control the smallest tick unit for the axis (here you'll get nothing less than one day) but also leaves the option for the axis to select a larger tick unit when there would otherwise be overlapping labels. And you get to specify the format that you want for each size.
I ran into a bit of trouble getting the Day.class tick labels to show anything other than zero. The following is the code I had to use with comments:

Code: Select all

    public void setChartTimeGranularity (Class timeUnit)
    {
        String label;
        XYPlot plot = chart.getXYPlot ();
        DateAxis axis = (DateAxis)plot.getDomainAxis ();
        final TickUnits standardUnits = new TickUnits ();
        
        if (timeUnit == Day.class)
        {
            calendarUnit = Calendar.DAY_OF_MONTH;
            standardUnits.add (new DateTickUnit (DateTickUnit.DAY, 1));
            standardUnits.add(new DateTickUnit(DateTickUnit.DAY, 7));
            // This was the only way I could get the date values to show.
            axis.setDateFormatOverride (new SimpleDateFormat ("MMM/d"));
            
            /*
             * I could not get this code to provide real data on the X axis
             * it always provided simply "0" for each data point, no 
             * matter what I tried....
            standardUnits.add (new DateTickUnit (DateTickUnit.DAY, 2, 
                new SimpleDateFormat ("MMM/d")));
            standardUnits.add (new DateTickUnit (DateTickUnit.DAY, 7, 
                new SimpleDateFormat ("MMM/d")));
            standardUnits.add (new DateTickUnit (DateTickUnit.MONTH, 1, 
                new SimpleDateFormat ("MMM")));
             */
            label = "Time (Month/Day)";
        }
        else if (timeUnit == Hour.class)
        {
            calendarUnit = Calendar.HOUR_OF_DAY;
            // this however worked fine!
            standardUnits.add (new DateTickUnit (DateTickUnit.HOUR, 1,
                new SimpleDateFormat ("H")));
            axis.setDateFormatOverride (null);
            label = "Time (Hours)";
        }
        else 
        {
            calendarUnit = Calendar.MINUTE;
            // This works fine too....
            standardUnits.add (new DateTickUnit (DateTickUnit.MINUTE, 1,
                new SimpleDateFormat ("m")));
            axis.setDateFormatOverride (null);
            label = "Time (Minutes)";
        }
        this.timeUnit = timeUnit;
        
        axis.setStandardTickUnits (standardUnits);
        axis.setLabel (label);
    }
Thanks again for your help!

-Dennis

Locked