Problem for displaying tick without label on axis

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
dropsy
Posts: 9
Joined: Wed Jul 19, 2006 4:12 pm
Location: Rennes, France

Problem for displaying tick without label on axis

Post by dropsy » Mon Jul 31, 2006 3:29 pm

Hello,

I get troubles to configure the display of my domain axis (the x-axis).
The x-axis is a time serie with one value for each day of the period (which is a month, from may 2006, 17th to june 2006, 16th for example).
I need to
- display a tick on my x-axis for every day in my period
- display a day number as a label for every 5 day period (for example, i have to display 17, 22, 27, 1, etc.) and the first day displayed must be the first day of my period (the 17).

since my english is poor, i made a picture of what i need to do:
Image

For the moment, i have that:
Image

Whith this code:

Code: Select all

JFreeChart chart = ChartFactory.createTimeSeriesChart("",libJours,libNbAppels,createDataset(nbAppels,""),false,false,false);
(...)
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setAutoRangeIncludesZero(true);
plot.setRangeAxis(rangeAxis);
DateAxis axis = (DateAxis) plot.getDomainAxis();
axis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, 5, new SimpleDateFormat("d")));
axis.setTickMarkPosition(DateTickMarkPosition.START);
Thanks for your help,

Regards
Patrick

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 Jul 31, 2006 4:10 pm

The DateAxis can't do this out-of-the-box, so you are going to have to modify it. Subclassing and overriding the refreshTicks() method is probably enough to do it...
David Gilbert
JFreeChart Project Leader

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

dropsy
Posts: 9
Joined: Wed Jul 19, 2006 4:12 pm
Location: Rennes, France

Post by dropsy » Mon Jul 31, 2006 4:28 pm

Ok, thank you for your answer David, i'll have a look at this method source to see how to do it.
But, is there a way to simply specify the first displayed date so that i can have a 17 as first date instead of 20 as on my example? Or do i need to extend DateAxis for this too?

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 Jul 31, 2006 4:45 pm

dropsy wrote:But, is there a way to simply specify the first displayed date so that i can have a 17 as first date instead of 20 as on my example? Or do i need to extend DateAxis for this too?
No. Yes.
David Gilbert
JFreeChart Project Leader

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

dropsy
Posts: 9
Joined: Wed Jul 19, 2006 4:12 pm
Location: Rennes, France

Post by dropsy » Mon Jul 31, 2006 5:27 pm

ok, thx for your answers.

velazquezs
Posts: 8
Joined: Tue Apr 11, 2006 11:10 pm

Post by velazquezs » Wed Aug 16, 2006 1:36 am

I've seen some post with this common need to modify refreshTicks on DateAxis to display some custom tick labels marks. Does any one have a reference on how to do this?

Thanks!

dropsy
Posts: 9
Joined: Wed Jul 19, 2006 4:12 pm
Location: Rennes, France

Post by dropsy » Fri Aug 25, 2006 5:21 pm

Well, here is what i did to solve my problem.
I extend 2 classes from JFreeChart:
  • DateTickUnit

Code: Select all

public class RepartDateTickUnit extends DateTickUnit {

	/**
	 * Creates a new date tick unit.  You can specify the units using one of 
	 * the constants YEAR, MONTH, DAY, HOUR, MINUTE, SECOND or MILLISECOND.  
	 * In addition, you can specify a unit count, and a date format.
	 *
	 * @param unit  the unit.
	 * @param count  the unit count.
	 * @param formatter  the date formatter (defaults to DateFormat.SHORT).
	 */
	public RepartDateTickUnit(int unit, int count, DateFormat formatter) {
		super(unit, count, unit, count, formatter);
	}


	/**
	 * Calculates the next date by adding one unit to the base date.
	 *
	 * @param base  the base date.
	 *
	 * @return A new date one unit after the base date.
	 */
	public Date nextDate(Date base) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(base);
		calendar.add(getCalendarField(getUnit()), 1);
		return calendar.getTime();

	}
	
	
	/**
	 * Returns a field code (that can be used with the Calendar class) for a 
	 * given 'unit' code.  The 'unit' is one of:  {@link #YEAR}, {@link #MONTH},
	 * {@link #DAY}, {@link #HOUR}, {@link #MINUTE}, {@link #SECOND} and 
	 * {@link #MILLISECOND}.
	 *
	 * @param tickUnit  the unit.
	 *
	 * @return The field code.
	 */
	private int getCalendarField(int tickUnit) {

		switch (tickUnit) {
			case (YEAR):
				return Calendar.YEAR;
			case (MONTH):
				return Calendar.MONTH;
			case (DAY):
				return Calendar.DATE;
			case (HOUR):
				return Calendar.HOUR_OF_DAY;
			case (MINUTE):
				return Calendar.MINUTE;
			case (SECOND):
				return Calendar.SECOND;
			case (MILLISECOND):
				return Calendar.MILLISECOND;
			default:
				return Calendar.MILLISECOND;
		}

	}
	
}
  • DateAxis

Code: Select all

public class RepartDateAxis extends DateAxis {
	/**
	 * Indique si on affiche les dates standards JFreeChart ou la première date de la période
	 */
	private boolean displayFirstDate = false;
	
	protected List refreshTicksHorizontal(Graphics2D g2,
										  Rectangle2D dataArea,
										  RectangleEdge edge) {

		List result = new java.util.ArrayList();

		Font tickLabelFont = getTickLabelFont();
		g2.setFont(tickLabelFont);

		if (isAutoTickUnitSelection()) {
			selectAutoTickUnit(g2, dataArea, edge);
		}

		RepartDateTickUnit unit = (RepartDateTickUnit) getTickUnit();
		Date tickDate = calculateLowestVisibleTickValue(unit);
		Date tickNoDate = getMinimumDate();
		Date upperDate = getMaximumDate();
		// float lastX = Float.MIN_VALUE;
		while (tickDate.before(upperDate) || tickNoDate.before(upperDate)) {
			TextAnchor anchor = null;
			TextAnchor rotationAnchor = null;
			double angle = 0.0;
			if (isVerticalTickLabels()) {
				anchor = TextAnchor.CENTER_RIGHT;
				rotationAnchor = TextAnchor.CENTER_RIGHT;
				if (edge == RectangleEdge.TOP) {
					angle = Math.PI / 2.0;
				}
				else {
					angle = -Math.PI / 2.0;
				}
			}
			else {
				if (edge == RectangleEdge.TOP) {
					anchor = TextAnchor.BOTTOM_CENTER;
					rotationAnchor = TextAnchor.BOTTOM_CENTER;
				}
				else {
					anchor = TextAnchor.TOP_CENTER;
					rotationAnchor = TextAnchor.TOP_CENTER;
				}
			}

			// add tick with no label
			while(tickNoDate.before(tickDate)){
				Tick tick = new DateTick(tickNoDate, "", anchor, rotationAnchor, angle);
				result.add(tick);
				tickNoDate = unit.nextDate(tickNoDate);
			}
			tickNoDate = unit.nextDate(tickNoDate);
			if (!isHiddenValue(tickDate.getTime())) {
				// work out the value, label and position
				String tickLabel;
				DateFormat formatter = getDateFormatOverride();
				if (formatter != null) {
					tickLabel = formatter.format(tickDate);
				}
				else {
					tickLabel = this.getTickUnit().dateToString(tickDate);
				}


				Tick tick = new DateTick(
					tickDate, tickLabel, anchor, rotationAnchor, angle
				);
				result.add(tick);
				tickDate = unit.addToDate(tickDate);
			}
			else {
				tickDate = unit.rollDate(tickDate);
			}
		}
		return result;
	}

	/**
	 * Calculates the value of the lowest visible tick on the axis.
	 *
	 * @param unit  date unit to use.
	 *
	 * @return The value of the lowest visible tick on the axis.
	 */
	public Date calculateLowestVisibleTickValue(DateTickUnit unit) {
		if(isDisplayFirstDate()){
			return getMinimumDate();
		} else {
			return nextStandardDate(getMinimumDate(), unit);
		}
	}

	/**
	 * @return
	 */
	public boolean isDisplayFirstDate() {
		return displayFirstDate;
	}

	/**
	 * @param b
	 */
	public void setDisplayFirstDate(boolean b) {
		displayFirstDate = b;
	}

}
Using these classes, every ticks on the domainAxis are displayed and, when setting the boolean displayFirstDate at true, the first date displayed on the domainAxis is the first date of the period.

this thread (http://www.jfree.org/phpBB2/viewtopic.php?t=18240) deals withthis subject too.

Dropsy
Last edited by dropsy on Sun Aug 27, 2006 7:58 pm, edited 1 time in total.

velazquezs
Posts: 8
Joined: Tue Apr 11, 2006 11:10 pm

Post by velazquezs » Sat Aug 26, 2006 12:14 am

Thanks dropsy,

Actually in the thread you mention, jwenting posted some code snipets too and with those I could succesfully resolve the need I had.

Thanks for this code that you provided here. One think I could not do it was to force to add the upperDate to the tick mark labels with out the labels fallling out of the chart space, do you know how could this be resolved?

Cheers!

Samuel.

dropsy
Posts: 9
Joined: Wed Jul 19, 2006 4:12 pm
Location: Rennes, France

Post by dropsy » Sun Aug 27, 2006 8:04 pm

Well, with the code of jwenting in the other thread, i could not compile becouse of a missing method (alignToUnit()).

For your problem, did you try to increase the margin of the chart? (perhaps it is the plot margin, i'll have a look at my code tomorrow to confirm that point)

Dropsy.

albamati
Posts: 7
Joined: Thu Jul 13, 2006 3:40 pm

How change the code

Post by albamati » Tue Sep 05, 2006 11:18 am

Thx for the code.
There is a way to add a parameter, to select the nmber of tick to show.

For example, show a tick for each 4 unit, and a label every 8.
This because choosing tick distances, you select also the gridline distance.

Thank you,
Alberto

albamati
Posts: 7
Joined: Thu Jul 13, 2006 3:40 pm

Errata

Post by albamati » Tue Sep 05, 2006 11:19 am

I forgot to put a ?...
so:


Is there a way to add a parameter, to select the number of tick to show?

dropsy
Posts: 9
Joined: Wed Jul 19, 2006 4:12 pm
Location: Rennes, France

Post by dropsy » Sun Sep 10, 2006 11:10 pm

Sorry, but I didn't implement this functionnality.

Locked