I have the following case wher I have just 2 dates and a
custom date format ("MMM yyyy"). The resulting chart
(viwed at 800x600 frame size) shows the label "Dez
2003" four times instead of "Dez 2003" one time
and "Jan 2004" one time:
/**
* This chart uses a date axis for X and shows a bug
with the automatic label generation. Instead of
generating 2 Labels for
* the 2 different dates, it generates 4 labels with the
same text value ("Dez 2003") of the first time series date
(2003-12-31)
* ignoring the second time series date (2004-01-31).
*
* Tested with JFreeChart 1.0.0-rc1
*
* @return JFreeChart.
*/
private JFreeChart testDateAxis1() {
JFreeChart result = null;
TimeSeriesCollection ds = new
TimeSeriesCollection();
TimeSeries ts = new TimeSeries("series1",
Month.class);
SimpleDateFormat sdf = new SimpleDateFormat
("yyyy-MM-dd");
sdf.setLenient(false); //strict parsing
ts.add(new Month(sdf.parse("2003-12-31", new
ParsePosition(0))), new BigDecimal(100.0));
ts.add(new Month(sdf.parse("2004-01-31", new
ParsePosition(0))), new BigDecimal(106.0));
ds.addSeries(ts);
result = ChartFactory.createTimeSeriesChart
("Time Series Chart", "X", "Y", ds, true, false, false);
//set date format that causes the trouble:
XYPlot xyPlot = result.getXYPlot();
DateAxis da = (DateAxis) xyPlot.getDomainAxis();
DateFormat df = da.getDateFormatOverride();
df = new SimpleDateFormat("MMM yyyy");
da.setDateFormatOverride(df);
return result;
}//testDateAxis1()
Output chart showing wrong labels
Logged In: YES
user_id=1365076
I think the problem is that you are misusing the DateFormat:
you can better achieve what you wish by creating a custom
"TickUnitSource" and setting it on your DateAxis. Have a
look at the code in
"DateAxis.createStandardDateTickUnits(Timezone)" to see how
TickUnitSource works.
The tick unit source contains the "natural" increments: a
number of DateTickUnits, each with a formatter, and
crucially, the unit (DAY, MONTH, YEAR) and number specifying
how many days, months, years...
If you provide just the formatter, there is no way for the
framework to see what kind of precision the formatter
provides: it is just a text formatter. You know it is
accurate to monthly increments, but the framework can't
figure that out. In your case, the framework has figured out
that it can fit 2-week interval labels on your axis, and
does so, but you force it to print only the months, and so
you get repeated labels.
Solution is: DateTickUnits do provide the level of
precision, and the framework can access this.
The TickUnitSource is a collection of (Date)TickUnits and is
handy because the framework will then choose the most
fine-grained timeunit that will fit on the axis, without the
labels overlapping.
If you are sure you always want one-month intervals, you can
also create a:
> DateTickUnit myUnit = new DateTickUnit(DateTickUnit.MONTH,
1, new SimpleDateFormatter());
and set it on your DateAxis with:
> DateAxis.setTickUnit(myUnit, true, true);
Hope this helps. I don't think what you report is a bug though.
Logged In: YES
user_id=667728
> DateTickUnit myUnit = new DateTickUnit
(DateTickUnit.MONTH,
1, new SimpleDateFormatter());
and set it on your DateAxis with:
> DateAxis.setTickUnit(myUnit, true, true);
Hope this helps. I don't think what you report is a bug though.
YOur workaround doesn't work (for all cases). Because by
setting it fixed to 1 month, all labels will overlapp if you have
too many labels, so the automatic won't work anymore.
Logged In: YES
user_id=1365076
I wasn't sure whether the framework would check that, and
unfortunately I guess it doesn't.
I suggested you look at "TickUnitSource", and this certainly
does look at how much space is available to each label and
automatically picks the one that fits best. Unfortunately,
it's relationship with SegmentedTimeline can be described as
disfunctional at best: I'm currently busy trying to fix the
labelling when you use SegmentedTimeline, because I get
overlaps there too.
Logged In: YES
user_id=112975
The setDateFormatOverride() method only overrides the tick
label format, it doesn't override the tick size. So you
have to be careful not to specify an inappropriate format
(i.e. one that won't differentiate between two dates that
are a single tick unit apart).
A better approach would be to use a custom tick unit
collection for the axis that doesn't include any units less
than one month (so this will become the minimum tick size):
DateAxis axis = (DateAxis) plot.getDomainAxis();
// customise the standard tick units...
DateFormat f1 = new SimpleDateFormat("MMM yyyy");
DateFormat f2 = new SimpleDateFormat("yyyy");
TickUnits standardUnits = new TickUnits();
standardUnits.add(new
DateTickUnit(DateTickUnit.MONTH, 1, f1));
standardUnits.add(new
DateTickUnit(DateTickUnit.MONTH, 2, f1));
standardUnits.add(new
DateTickUnit(DateTickUnit.MONTH, 3, f1));
standardUnits.add(new
DateTickUnit(DateTickUnit.MONTH, 4, f1));
standardUnits.add(new
DateTickUnit(DateTickUnit.MONTH, 6, f1));
standardUnits.add(new
DateTickUnit(DateTickUnit.YEAR, 1, f2));
standardUnits.add(new
DateTickUnit(DateTickUnit.YEAR, 2, f2));
standardUnits.add(new
DateTickUnit(DateTickUnit.YEAR, 5, f2));
standardUnits.add(new
DateTickUnit(DateTickUnit.YEAR, 10, f2));
axis.setStandardTickUnits(standardUnits);
Regards,
Dave Gilbert
JFreeChart Project Leader
Logged In: YES
user_id=667728
Originator: YES
Seems to work with 1.0.3 now.