dateaxis.java
来自「JfreeChart 常用图表例子」· Java 代码 · 共 1,787 行 · 第 1/5 页
JAVA
1,787 行
DateTickUnit.MINUTE, 20, DateTickUnit.MINUTE, 5, f3 ) ); units.add( new DateTickUnit( DateTickUnit.MINUTE, 30, DateTickUnit.MINUTE, 5, f3 ) ); // hours units.add( new DateTickUnit(DateTickUnit.HOUR, 1, DateTickUnit.MINUTE, 5, f3) ); units.add( new DateTickUnit(DateTickUnit.HOUR, 2, DateTickUnit.MINUTE, 10, f3) ); units.add( new DateTickUnit(DateTickUnit.HOUR, 4, DateTickUnit.MINUTE, 30, f3) ); units.add( new DateTickUnit(DateTickUnit.HOUR, 6, DateTickUnit.HOUR, 1, f3) ); units.add( new DateTickUnit(DateTickUnit.HOUR, 12, DateTickUnit.HOUR, 1, f4) ); // days units.add( new DateTickUnit(DateTickUnit.DAY, 1, DateTickUnit.HOUR, 1, f5) ); units.add( new DateTickUnit(DateTickUnit.DAY, 2, DateTickUnit.HOUR, 1, f5) ); units.add( new DateTickUnit(DateTickUnit.DAY, 7, DateTickUnit.DAY, 1, f5) ); units.add( new DateTickUnit(DateTickUnit.DAY, 15, DateTickUnit.DAY, 1, f5) ); // months units.add( new DateTickUnit(DateTickUnit.MONTH, 1, DateTickUnit.DAY, 1, f6) ); units.add( new DateTickUnit(DateTickUnit.MONTH, 2, DateTickUnit.DAY, 1, f6) ); units.add( new DateTickUnit(DateTickUnit.MONTH, 3, DateTickUnit.MONTH, 1, f6) ); units.add( new DateTickUnit(DateTickUnit.MONTH, 4, DateTickUnit.MONTH, 1, f6) ); units.add( new DateTickUnit(DateTickUnit.MONTH, 6, DateTickUnit.MONTH, 1, f6) ); // years units.add( new DateTickUnit(DateTickUnit.YEAR, 1, DateTickUnit.MONTH, 1, f7) ); units.add( new DateTickUnit(DateTickUnit.YEAR, 2, DateTickUnit.MONTH, 3, f7) ); units.add( new DateTickUnit(DateTickUnit.YEAR, 5, DateTickUnit.YEAR, 1, f7) ); units.add( new DateTickUnit(DateTickUnit.YEAR, 10, DateTickUnit.YEAR, 1, f7) ); units.add( new DateTickUnit(DateTickUnit.YEAR, 25, DateTickUnit.YEAR, 5, f7) ); units.add( new DateTickUnit(DateTickUnit.YEAR, 50, DateTickUnit.YEAR, 10, f7) ); units.add( new DateTickUnit(DateTickUnit.YEAR, 100, DateTickUnit.YEAR, 20, f7) ); return units; } /** * Rescales the axis to ensure that all data is visible. */ protected void autoAdjustRange() { Plot plot = getPlot(); if (plot == null) { return; // no plot, no data } if (plot instanceof ValueAxisPlot) { ValueAxisPlot vap = (ValueAxisPlot) plot; Range r = vap.getDataRange(this); if (r == null) { if (this.timeline instanceof SegmentedTimeline) { //Timeline hasn't method getStartTime() r = new DateRange( ((SegmentedTimeline) this.timeline).getStartTime(), ((SegmentedTimeline) this.timeline).getStartTime() + 1 ); } else { r = new DateRange(); } } long upper = this.timeline.toTimelineValue( (long) r.getUpperBound() ); long lower; long fixedAutoRange = (long) getFixedAutoRange(); if (fixedAutoRange > 0.0) { lower = upper - fixedAutoRange; } else { lower = this.timeline.toTimelineValue((long) r.getLowerBound()); double range = upper - lower; long minRange = (long) getAutoRangeMinimumSize(); if (range < minRange) { long expand = (long) (minRange - range) / 2; upper = upper + expand; lower = lower - expand; } upper = upper + (long) (range * getUpperMargin()); lower = lower - (long) (range * getLowerMargin()); } upper = this.timeline.toMillisecond(upper); lower = this.timeline.toMillisecond(lower); DateRange dr = new DateRange(new Date(lower), new Date(upper)); setRange(dr, false, false); } } /** * Selects an appropriate tick value for the axis. The strategy is to * display as many ticks as possible (selected from an array of 'standard' * tick units) without the labels overlapping. * * @param g2 the graphics device. * @param dataArea the area defined by the axes. * @param edge the axis location. */ protected void selectAutoTickUnit(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) { if (RectangleEdge.isTopOrBottom(edge)) { selectHorizontalAutoTickUnit(g2, dataArea, edge); } else if (RectangleEdge.isLeftOrRight(edge)) { selectVerticalAutoTickUnit(g2, dataArea, edge); } } /** * Selects an appropriate tick size for the axis. The strategy is to * display as many ticks as possible (selected from a collection of * 'standard' tick units) without the labels overlapping. * * @param g2 the graphics device. * @param dataArea the area defined by the axes. * @param edge the axis location. */ protected void selectHorizontalAutoTickUnit(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) { long shift = 0; if (this.timeline instanceof SegmentedTimeline) { shift = ((SegmentedTimeline) this.timeline).getStartTime(); } double zero = valueToJava2D(shift + 0.0, dataArea, edge); double tickLabelWidth = estimateMaximumTickLabelWidth(g2, getTickUnit()); // start with the current tick unit... TickUnitSource tickUnits = getStandardTickUnits(); TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit()); double x1 = valueToJava2D(shift + unit1.getSize(), dataArea, edge); double unit1Width = Math.abs(x1 - zero); // then extrapolate... double guess = (tickLabelWidth / unit1Width) * unit1.getSize(); DateTickUnit unit2 = (DateTickUnit) tickUnits.getCeilingTickUnit(guess); double x2 = valueToJava2D(shift + unit2.getSize(), dataArea, edge); double unit2Width = Math.abs(x2 - zero); tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2); if (tickLabelWidth > unit2Width) { unit2 = (DateTickUnit) tickUnits.getLargerTickUnit(unit2); } setTickUnit(unit2, false, false); } /** * Selects an appropriate tick size for the axis. The strategy is to * display as many ticks as possible (selected from a collection of * 'standard' tick units) without the labels overlapping. * * @param g2 the graphics device. * @param dataArea the area in which the plot should be drawn. * @param edge the axis location. */ protected void selectVerticalAutoTickUnit(Graphics2D g2, Rectangle2D dataArea, RectangleEdge edge) { // start with the current tick unit... TickUnitSource tickUnits = getStandardTickUnits(); double zero = valueToJava2D(0.0, dataArea, edge); // start with a unit that is at least 1/10th of the axis length double estimate1 = getRange().getLength() / 10.0; DateTickUnit candidate1 = (DateTickUnit) tickUnits.getCeilingTickUnit(estimate1); double labelHeight1 = estimateMaximumTickLabelHeight(g2, candidate1); double y1 = valueToJava2D(candidate1.getSize(), dataArea, edge); double candidate1UnitHeight = Math.abs(y1 - zero); // now extrapolate based on label height and unit height... double estimate2 = (labelHeight1 / candidate1UnitHeight) * candidate1.getSize(); DateTickUnit candidate2 = (DateTickUnit) tickUnits.getCeilingTickUnit(estimate2); double labelHeight2 = estimateMaximumTickLabelHeight(g2, candidate2); double y2 = valueToJava2D(candidate2.getSize(), dataArea, edge); double unit2Height = Math.abs(y2 - zero); // make final selection... DateTickUnit finalUnit; if (labelHeight2 < unit2Height) { finalUnit = candidate2; } else { finalUnit = (DateTickUnit) tickUnits.getLargerTickUnit(candidate2); } setTickUnit(finalUnit, false, false); } /** * Estimates the maximum width of the tick labels, assuming the specified * tick unit is used. * <P> * Rather than computing the string bounds of every tick on the axis, we * just look at two values: the lower bound and the upper bound for the * axis. These two values will usually be representative. * * @param g2 the graphics device. * @param unit the tick unit to use for calculation. * * @return The estimated maximum width of the tick labels. */ private double estimateMaximumTickLabelWidth(Graphics2D g2, DateTickUnit unit) { RectangleInsets tickLabelInsets = getTickLabelInsets(); double result = tickLabelInsets.getLeft() + tickLabelInsets.getRight(); Font tickLabelFont = getTickLabelFont(); FontRenderContext frc = g2.getFontRenderContext(); LineMetrics lm = tickLabelFont.getLineMetrics("ABCxyz", frc); if (isVerticalTickLabels()) { // all tick labels have the same width (equal to the height of // the font)... result += lm.getHeight(); } else { // look at lower and upper bounds... DateRange range = (DateRange) getRange(); Date lower = range.getLowerDate(); Date upper = range.getUpperDate(); String lowerStr = null; String upperStr = null; DateFormat formatter = getDateFormatOverride(); if (formatter != null) { lowerStr = formatter.format(lower); upperStr = formatter.format(upper); } else { lowerStr = unit.dateToString(lower); upperStr = unit.dateToString(upper); } FontMetrics fm = g2.getFontMetrics(tickLabelFont); double w1 = fm.stringWidth(lowerStr); double w2 = fm.stringWidth(upperStr); result += Math.max(w1, w2); } return result; } /** * Estimates the maximum width of the tick labels, assuming the specified * tick unit is used. * <P> * Rather than computing the string bounds of every tick on the axis, we * just look at two values: the lower bound and the upper bound for the * axis. These two values will usually be representative. * * @param g2 the graphics device. * @param unit the tick unit to use for calculation. * * @return The estimated maximum width of the tick labels. */ private double estimateMaximumTickLabelHeight(Graphics2D g2, DateTickUnit unit) { RectangleInsets tickLabelInsets = getTickLabelInsets(); double result = tickLabelInsets.getTop() + tickLabelInsets.getBottom(); Font tickLabelFont = getTickLabelFont(); FontRenderContext frc = g2.getFontRenderContext(); LineMetrics lm = tickLabelFont.getLineMetrics("ABCxyz", frc); if (!isVerticalTickLabels()) { // all tick labels have the same width (equal to the height of // the font)... result += lm.getHeight(); } else { // look at lower and upper bounds... DateRange range = (DateRange) getRange(); Date lower = range.getLowerDate(); Date upper = range.getUpperDate(); String lowerStr = null; String upperStr = null; DateFormat formatter = getDateFormatOverride(); if (formatter != null) { lowerStr = formatter.format(lower); upperStr = formatter.format(upper); } else { lowerStr = unit.dateToString(lower); upperStr = unit.dateToString(upper); } FontMetrics fm = g2.getFontMetrics(tickLabelFont); double w1 = fm.stringWidth(lowerStr); double w2 = fm.stringWidth(upperStr); result += Math.max(w1, w2); } return result; } /** * Calculates the positions of the tick labels for the axis, storing the * results in the tick label list (ready for drawing). *
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?