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 + -
显示快捷键?