periodaxis.java
来自「JfreeChart 常用图表例子」· Java 代码 · 共 1,167 行 · 第 1/3 页
JAVA
1,167 行
label1, g2, g2.getFontMetrics() ); Rectangle2D b2 = TextUtilities.getTextBounds( label2, g2, g2.getFontMetrics() ); double w = Math.max(b1.getWidth(), b2.getWidth()); long ww = Math.round( java2DToValue(dataArea.getX() + w + 5.0, dataArea, edge) ) - axisMin; long length = p1.getLastMillisecond(this.timeZone) - p1.getFirstMillisecond(this.timeZone); int periods = (int) (ww / length) + 1; RegularTimePeriod p = this.labelInfo[band].createInstance( new Date(axisMin), this.timeZone ); Rectangle2D b = null; long lastXX = 0L; float y = (float) (state.getCursor()); TextAnchor anchor = TextAnchor.TOP_CENTER; float yDelta = (float) b1.getHeight(); if (edge == RectangleEdge.TOP) { anchor = TextAnchor.BOTTOM_CENTER; yDelta = -yDelta; } while (p.getFirstMillisecond(this.timeZone) <= axisMax) { float x = (float) valueToJava2D( p.getMiddleMillisecond(this.timeZone), dataArea, edge ); DateFormat df = this.labelInfo[band].getDateFormat(); String label = df.format( new Date(p.getMiddleMillisecond(this.timeZone)) ); long first = p.getFirstMillisecond(this.timeZone); long last = p.getLastMillisecond(this.timeZone); if (last > axisMax) { // this is the last period, but it is only partially visible // so check that the label will fit before displaying it... Rectangle2D bb = TextUtilities.getTextBounds( label, g2, g2.getFontMetrics() ); if ((x + bb.getWidth() / 2) > dataArea.getMaxX()) { float xstart = (float) valueToJava2D( Math.max(first, axisMin), dataArea, edge ); if (bb.getWidth() < (dataArea.getMaxX() - xstart)) { x = ((float) dataArea.getMaxX() + xstart) / 2.0f; } else { label = null; } } } if (first < axisMin) { // this is the first period, but it is only partially visible // so check that the label will fit before displaying it... Rectangle2D bb = TextUtilities.getTextBounds( label, g2, g2.getFontMetrics() ); if ((x - bb.getWidth() / 2) < dataArea.getX()) { float xlast = (float) valueToJava2D( Math.min(last, axisMax), dataArea, edge ); if (bb.getWidth() < (xlast - dataArea.getX())) { x = (xlast + (float) dataArea.getX()) / 2.0f; } else { label = null; } } } if (label != null) { g2.setPaint(this.labelInfo[band].getLabelPaint()); b = TextUtilities.drawAlignedString(label, g2, x, y, anchor); } if (lastXX > 0L) { if (this.labelInfo[band].getDrawDividers()) { long nextXX = p.getFirstMillisecond(this.timeZone); long mid = (lastXX + nextXX) / 2; float mid2d = (float) valueToJava2D(mid, dataArea, edge); g2.setStroke(this.labelInfo[band].getDividerStroke()); g2.setPaint(this.labelInfo[band].getDividerPaint()); g2.draw( new Line2D.Float(mid2d, y, mid2d, y + yDelta) ); } } lastXX = last; for (int i = 0; i < periods; i++) { p = p.next(); } } double used = 0.0; if (b != null) { used = b.getHeight(); // work out the trailing gap if (edge == RectangleEdge.BOTTOM) { used += this.labelInfo[band].getPadding().calculateBottomOutset( fm.getHeight() ); } else if (edge == RectangleEdge.TOP) { used += this.labelInfo[band].getPadding().calculateTopOutset( fm.getHeight() ); } } state.moveCursor(used, edge); return state; } /** * Calculates the positions of the ticks for the axis, storing the results * in the tick list (ready for drawing). * * @param g2 the graphics device. * @param state the axis state. * @param dataArea the area inside the axes. * @param edge the edge on which the axis is located. * * @return The list of ticks. */ public List refreshTicks(Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) { return Collections.EMPTY_LIST; } /** * Converts a data value to a coordinate in Java2D space, assuming that the * axis runs along one edge of the specified dataArea. * <p> * Note that it is possible for the coordinate to fall outside the area. * * @param value the data value. * @param area the area for plotting the data. * @param edge the edge along which the axis lies. * * @return The Java2D coordinate. */ public double valueToJava2D(double value, Rectangle2D area, RectangleEdge edge) { double result = Double.NaN; double axisMin = this.first.getFirstMillisecond(this.timeZone); double axisMax = this.last.getLastMillisecond(this.timeZone); if (RectangleEdge.isTopOrBottom(edge)) { double minX = area.getX(); double maxX = area.getMaxX(); if (isInverted()) { result = maxX + ((value - axisMin) / (axisMax - axisMin)) * (minX - maxX); } else { result = minX + ((value - axisMin) / (axisMax - axisMin)) * (maxX - minX); } } else if (RectangleEdge.isLeftOrRight(edge)) { double minY = area.getMinY(); double maxY = area.getMaxY(); if (isInverted()) { result = minY + (((value - axisMin) / (axisMax - axisMin)) * (maxY - minY)); } else { result = maxY - (((value - axisMin) / (axisMax - axisMin)) * (maxY - minY)); } } return result; } /** * Converts a coordinate in Java2D space to the corresponding data value, * assuming that the axis runs along one edge of the specified dataArea. * * @param java2DValue the coordinate in Java2D space. * @param area the area in which the data is plotted. * @param edge the edge along which the axis lies. * * @return The data value. */ public double java2DToValue(double java2DValue, Rectangle2D area, RectangleEdge edge) { double result = Double.NaN; double min = 0.0; double max = 0.0; double axisMin = this.first.getFirstMillisecond(this.timeZone); double axisMax = this.last.getLastMillisecond(this.timeZone); if (RectangleEdge.isTopOrBottom(edge)) { min = area.getX(); max = area.getMaxX(); } else if (RectangleEdge.isLeftOrRight(edge)) { min = area.getMaxY(); max = area.getY(); } if (isInverted()) { result = axisMax - ((java2DValue - min) / (max - min) * (axisMax - axisMin)); } else { result = axisMin + ((java2DValue - min) / (max - min) * (axisMax - axisMin)); } return result; } /** * 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) { r = new Range(DEFAULT_LOWER_BOUND, DEFAULT_UPPER_BOUND); } long upper = Math.round(r.getUpperBound()); long lower = Math.round(r.getLowerBound()); this.first = createInstance( this.autoRangeTimePeriodClass, new Date(lower), this.timeZone ); this.last = createInstance( this.autoRangeTimePeriodClass, new Date(upper), this.timeZone ); } } /** * Tests the axis for equality with an arbitrary object. * * @param obj the object (<code>null</code> permitted). * * @return A boolean. */ public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof PeriodAxis && super.equals(obj)) { PeriodAxis that = (PeriodAxis) obj; if (!this.first.equals(that.first)) { return false; } if (!this.last.equals(that.last)) { return false; } if (!this.timeZone.equals(that.timeZone)) { return false; } if (!this.autoRangeTimePeriodClass.equals( that.autoRangeTimePeriodClass )) { return false; } if (!(isMinorTickMarksVisible() == that.isMinorTickMarksVisible())) { return false; } if (!this.majorTickTimePeriodClass.equals( that.majorTickTimePeriodClass)) { return false; } if (!this.minorTickTimePeriodClass.equals( that.minorTickTimePeriodClass)) { return false; } if (!this.minorTickMarkPaint.equals(that.minorTickMarkPaint)) { return false; } if (!this.minorTickMarkStroke.equals(that.minorTickMarkStroke)) { return false; } if (!Arrays.equals(this.labelInfo, that.labelInfo)) { return false; } return true; } return false; } /** * Returns a hash code for this object. * * @return A hash code. */ public int hashCode() { if (getLabel() != null) { return getLabel().hashCode(); } else { return 0; } } /** * Returns a clone of the axis. * * @return A clone. * * @throws CloneNotSupportedException this class is cloneable, but * subclasses may not be. */ public Object clone() throws CloneNotSupportedException { PeriodAxis clone = (PeriodAxis) super.clone(); clone.timeZone = (TimeZone) this.timeZone.clone(); clone.labelInfo = new PeriodAxisLabelInfo[this.labelInfo.length]; for (int i = 0; i < this.labelInfo.length; i++) { clone.labelInfo[i] = this.labelInfo[i]; // copy across references // to immutable objs } return clone; } /** * A utility method used to create a particular subclass of the * {@link RegularTimePeriod} class that includes the specified millisecond, * assuming the specified time zone. * * @param periodClass the class. * @param millisecond the time. * @param zone the time zone. * * @return The time period. */ private RegularTimePeriod createInstance(Class periodClass, Date millisecond, TimeZone zone) { RegularTimePeriod result = null; try { Constructor c = periodClass.getDeclaredConstructor( new Class[] {Date.class, TimeZone.class} ); result = (RegularTimePeriod) c.newInstance( new Object[] {millisecond, zone} ); } catch (Exception e) { // do nothing } return result; } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtilities.writeStroke(this.minorTickMarkStroke, stream); SerialUtilities.writePaint(this.minorTickMarkPaint, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.minorTickMarkStroke = SerialUtilities.readStroke(stream); this.minorTickMarkPaint = SerialUtilities.readPaint(stream); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?