在 JFreeChart 中创建以周为单位的自定义 DateTickUnitType
据我所知,DateTickUnitType 是一个枚举,除了彻底替换之外无法扩展或更改,它只指定 DAY、MONTH、YEAR、MINUTE、HOUR、SECOND 和 MILLISECOND 的单位,但不指定 WEEK 的单位,尽管存在 Week 类型时间段。
这导致的问题是,当我被迫使用 DAY 刻度单位来绘制一周的单个数据点时,与在 DAY 刻度单位上绘制每日点或在月刻度单位。
根据我的数据范围(我以编程方式计算),我使用最合适的 TimePeriod 创建 TimeSeriesDataItem:
// create the correct TimeSeriesDataItem based on the gap of this data set
switch (gap) {
case WEEK:
item = new TimeSeriesDataItem(new Week(targetDate.getTime()), dataPoint);
break;
case DAY:
item = new TimeSeriesDataItem(new Day(targetDate.getTime()), dataPoint);
break;
case MONTH:
default:
item = new TimeSeriesDataItem(new Month(targetDate.getTime()), dataPoint);
break;
}
然后在构建图表后,我尝试对其进行自定义,以使每个数据点的条形尽可能宽。如果数据为天,则刻度单位为天。如果数据为月,则刻度单位为月。但如果数据是几周,那么我就被迫要么用几天,要么用几个月,因为没有周刻度单位。
JFreeChart barChart = ChartFactory.createXYBarChart(
model.getTitle(),
model.getDomainTitle(),
true,
model.getRangeTitle(),
dataset,
model.getOrientation() == SimpleBarChartModel.Orientation.VERTICAL ? PlotOrientation.VERTICAL : PlotOrientation.HORIZONTAL,
model.getShowLegend(),
false,
false);
// ...
DateAxis domainAxis = (DateAxis)plot.getDomainAxis();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
if (model.getDomainLabels() != null && model.getDomainLabels().size() > 1) {
// create three different sets of TickUnits for the three ranges (day, week, month)
// JFreeChart will select the smallest unit that doesn't overlap labels.
TickUnits tickUnits = new TickUnits();
tickUnits.add(new DateTickUnit(DateTickUnitType.MONTH, 1, new SimpleDateFormat("MMM")));
tickUnits.add(new DateTickUnit(DateTickUnitType.DAY, 7, dateFormat));
tickUnits.add(new DateTickUnit(DateTickUnitType.DAY, 1, dateFormat));
domainAxis.setStandardTickUnits(tickUnits);
}
domainAxis.setAutoRange(true);
domainAxis.setVerticalTickLabels(true);
domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
前者创建的条形非常细,因为它每个刻度单位绘制 7 列。
有什么方法可以为 WEEK 制作一个自定义 DateTickUnitType ,让我每周只绘制一个点而不是 7 个点(因为我只有一个数据点)?
From what I can tell DateTickUnitType is an enumeration that cannot be extended or changed outside of outright replacement and it only specifies units for DAY, MONTH, YEAR, MINUTE, HOUR, SECOND, and MILLISECOND, but not WEEK despite there being a Week type of TimePeriod.
The problem this causes is when I am forced to use the DAY tick unit to plot a single data point for a week which leaves my bar width quite narrow as compared to plotting a daily point on a DAY tick unit or a monthly data point on a MONTH tick unit.
Depending on the range of my data (which I calculate programmatically), I create the TimeSeriesDataItem with the most appropriate TimePeriod:
// create the correct TimeSeriesDataItem based on the gap of this data set
switch (gap) {
case WEEK:
item = new TimeSeriesDataItem(new Week(targetDate.getTime()), dataPoint);
break;
case DAY:
item = new TimeSeriesDataItem(new Day(targetDate.getTime()), dataPoint);
break;
case MONTH:
default:
item = new TimeSeriesDataItem(new Month(targetDate.getTime()), dataPoint);
break;
}
And then after the chart is built, I try to customize it to make the bars as wide as possible for each data point. If the data are days, the tick units are days. If the data are months, the tick units are months. But if the data are weeks, then I'm forced to either go with days or months since there is no week tick unit.
JFreeChart barChart = ChartFactory.createXYBarChart(
model.getTitle(),
model.getDomainTitle(),
true,
model.getRangeTitle(),
dataset,
model.getOrientation() == SimpleBarChartModel.Orientation.VERTICAL ? PlotOrientation.VERTICAL : PlotOrientation.HORIZONTAL,
model.getShowLegend(),
false,
false);
// ...
DateAxis domainAxis = (DateAxis)plot.getDomainAxis();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
if (model.getDomainLabels() != null && model.getDomainLabels().size() > 1) {
// create three different sets of TickUnits for the three ranges (day, week, month)
// JFreeChart will select the smallest unit that doesn't overlap labels.
TickUnits tickUnits = new TickUnits();
tickUnits.add(new DateTickUnit(DateTickUnitType.MONTH, 1, new SimpleDateFormat("MMM")));
tickUnits.add(new DateTickUnit(DateTickUnitType.DAY, 7, dateFormat));
tickUnits.add(new DateTickUnit(DateTickUnitType.DAY, 1, dateFormat));
domainAxis.setStandardTickUnits(tickUnits);
}
domainAxis.setAutoRange(true);
domainAxis.setVerticalTickLabels(true);
domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
The former creates very thin bars since it's plotting 7 columns per tick unit.
Is there any way for me to make a custom DateTickUnitType for WEEK that would allow me to plot only one point per week instead of 7 (since I only have one data point)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于
DynamicTimeSeriesCollection
,您可以使用此处表示MILLISECOND
。另请参阅此后续线程,其中提到了所选的多个时期。For
DynamicTimeSeriesCollection
you can addWEEK
using the approach shown here forMILLISECOND
. See also this followup thread, which mentions multiples of the chosen period.