📄 candlestickrenderer.java
字号:
*/ public void setDownPaint(Paint paint) { this.downPaint = paint; notifyListeners(new RendererChangeEvent(this)); } /** * Returns a flag indicating whether or not volume bars are drawn on the * chart. * * @return <code>true</code> if volume bars are drawn on the chart. */ public boolean drawVolume() { return this.drawVolume; } /** * Sets a flag that controls whether or not volume bars are drawn in the * background. * * @param flag The flag. */ public void setDrawVolume(boolean flag) { if (this.drawVolume != flag) { this.drawVolume = flag; notifyListeners(new RendererChangeEvent(this)); } } /** * Initialises the renderer then returns the number of 'passes' through the data that the * renderer will require (usually just one). This method will be called before the first * item is rendered, giving the renderer an opportunity to initialise any * state information it wants to maintain. The renderer can do nothing if it chooses. * * @param g2 the graphics device. * @param dataArea the area inside the axes. * @param plot the plot. * @param dataset the data. * @param info an optional info collection object to return data back to the caller. * * @return The number of passes the renderer requires. */ public XYItemRendererState initialise(Graphics2D g2, Rectangle2D dataArea, XYPlot plot, XYDataset dataset, PlotRenderingInfo info) { // calculate the maximum allowed candle width from the axis... ValueAxis axis = plot.getDomainAxis(); double x1 = axis.getLowerBound(); double x2 = x1 + this.maxCandleWidthInMilliseconds; RectangleEdge edge = plot.getDomainAxisEdge(); double xx1 = axis.valueToJava2D(x1, dataArea, edge); double xx2 = axis.valueToJava2D(x2, dataArea, edge); this.maxCandleWidth = Math.abs(xx2 - xx1); // Absolute value, since the relative x // positions are reversed for horizontal orientation // calculate the highest volume in the dataset... if (this.drawVolume) { HighLowDataset highLowDataset = (HighLowDataset) dataset; this.maxVolume = 0.0; for (int series = 0; series < highLowDataset.getSeriesCount(); series++) { for (int item = 0; item < highLowDataset.getItemCount(series); item++) { double volume = highLowDataset.getVolumeValue(series, item).doubleValue(); if (volume > this.maxVolume) { this.maxVolume = volume; } } } } return new XYItemRendererState(info); } /** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the plot is being drawn. * @param info collects info about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot (<code>null</code> permitted). * @param pass the pass index. */ public void drawItem(Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { boolean horiz; PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { horiz = true; } else if (orientation == PlotOrientation.VERTICAL) { horiz = false; } else { return; } // setup for collecting optional entity info... EntityCollection entities = null; if (info != null) { entities = info.getOwner().getEntityCollection(); } HighLowDataset highLowData = (HighLowDataset) dataset; Number x = highLowData.getXValue(series, item); Number yHigh = highLowData.getHighValue(series, item); Number yLow = highLowData.getLowValue(series, item); Number yOpen = highLowData.getOpenValue(series, item); Number yClose = highLowData.getCloseValue(series, item); RectangleEdge domainEdge = plot.getDomainAxisEdge(); double xx = domainAxis.valueToJava2D(x.doubleValue(), dataArea, domainEdge); RectangleEdge edge = plot.getRangeAxisEdge(); double yyHigh = rangeAxis.valueToJava2D(yHigh.doubleValue(), dataArea, edge); double yyLow = rangeAxis.valueToJava2D(yLow.doubleValue(), dataArea, edge); double yyOpen = rangeAxis.valueToJava2D(yOpen.doubleValue(), dataArea, edge); double yyClose = rangeAxis.valueToJava2D(yClose.doubleValue(), dataArea, edge); double volumeWidth; double stickWidth; if (this.candleWidth > 0) { // These are deliberately not bounded to minimums/maxCandleWidth to retain old // behaviour. volumeWidth = this.candleWidth; stickWidth = this.candleWidth; } else { double xxWidth = 0; int itemCount; switch (this.autoWidthMethod) { case WIDTHMETHOD_AVERAGE: itemCount = highLowData.getItemCount(series); if (horiz) { xxWidth = dataArea.getHeight() / itemCount; } else { xxWidth = dataArea.getWidth() / itemCount; } break; case WIDTHMETHOD_SMALLEST: // Note: It would be nice to pre-calculate this per series itemCount = highLowData.getItemCount(series); double lastPos = -1; xxWidth = dataArea.getWidth(); for (int i = 0; i < itemCount; i++) { double pos = domainAxis.valueToJava2D( highLowData.getXValue(series, i).doubleValue(), dataArea, domainEdge ); if (lastPos != -1) { xxWidth = Math.min(xxWidth, Math.abs(pos - lastPos)); } lastPos = pos; } break; case WIDTHMETHOD_INTERVALDATA: IntervalXYDataset intervalXYData = (IntervalXYDataset) dataset; double startPos = domainAxis.valueToJava2D( intervalXYData.getStartXValue(series, item).doubleValue(), dataArea, plot.getDomainAxisEdge() ); double endPos = domainAxis.valueToJava2D( intervalXYData.getEndXValue(series, item).doubleValue(), dataArea, plot.getDomainAxisEdge() ); xxWidth = Math.abs(endPos - startPos); break; } xxWidth -= 2 * this.autoWidthGap; xxWidth *= this.autoWidthFactor; xxWidth = Math.min(xxWidth, this.maxCandleWidth); volumeWidth = Math.max(Math.min(1, this.maxCandleWidth), xxWidth); stickWidth = Math.max(Math.min(3, this.maxCandleWidth), xxWidth); } Paint p = getItemPaint(series, item); Stroke s = getItemStroke(series, item); g2.setStroke(s); if (this.drawVolume) { int volume = highLowData.getVolumeValue(series, item).intValue(); double volumeHeight = volume / this.maxVolume; double min, max; if (horiz) { min = dataArea.getMinX(); max = dataArea.getMaxX(); } else { min = dataArea.getMinY(); max = dataArea.getMaxY(); } double zzVolume = volumeHeight * (max - min); g2.setPaint(Color.gray); Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f)); if (horiz) { g2.fill(new Rectangle2D.Double(min, xx - volumeWidth / 2, zzVolume, volumeWidth)); } else { g2.fill(new Rectangle2D.Double(xx - volumeWidth / 2, max - zzVolume, volumeWidth, zzVolume)); } g2.setComposite(originalComposite); } g2.setPaint(p); double yyMaxOpenClose = Math.max(yyOpen, yyClose); double yyMinOpenClose = Math.min(yyOpen, yyClose); double maxOpenClose = Math.max(yOpen.doubleValue(), yClose.doubleValue()); double minOpenClose = Math.min(yOpen.doubleValue(), yClose.doubleValue()); // draw the upper shadow if (yHigh.doubleValue() > maxOpenClose) { if (horiz) { g2.draw(new Line2D.Double(yyHigh, xx, yyMaxOpenClose, xx)); } else { g2.draw(new Line2D.Double(xx, yyHigh, xx, yyMaxOpenClose)); } } // draw the lower shadow if (yLow.doubleValue() < minOpenClose) { if (horiz) { g2.draw(new Line2D.Double(yyLow, xx, yyMinOpenClose, xx)); } else { g2.draw(new Line2D.Double(xx, yyLow, xx, yyMinOpenClose)); } } // draw the body Shape body = null; if (horiz) { body = new Rectangle2D.Double(yyMinOpenClose, xx - stickWidth / 2, yyMaxOpenClose - yyMinOpenClose, stickWidth); } else { body = new Rectangle2D.Double(xx - stickWidth / 2, yyMinOpenClose, stickWidth, yyMaxOpenClose - yyMinOpenClose); } if (yClose.doubleValue() > yOpen.doubleValue()) { if (this.upPaint != null) { g2.setPaint(this.upPaint); g2.fill(body); } } else { if (this.downPaint != null) { g2.setPaint(this.downPaint); } g2.fill(body); } g2.setPaint(p); g2.draw(body); // add an entity for the item... if (entities != null) { String tip = null; XYToolTipGenerator generator = getToolTipGenerator(series, item); if (generator != null) { tip = generator.generateToolTip(dataset, series, item); } String url = null; if (getURLGenerator() != null) { url = getURLGenerator().generateURL(dataset, series, item); } XYItemEntity entity = new XYItemEntity(body, dataset, series, item, tip, url); entities.addEntity(entity); } } /** * Tests this renderer for equality with another object. * * @param obj the object. * * @return <code>true</code> or <code>false</code>. */ public boolean equals(Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (obj instanceof CandlestickRenderer) { CandlestickRenderer renderer = (CandlestickRenderer) obj; boolean result = super.equals(obj); result = result && (this.candleWidth == renderer.getCandleWidth()); result = result && (this.upPaint.equals(renderer.getUpPaint())); result = result && (this.downPaint.equals(renderer.getDownPaint())); result = result && (this.drawVolume == renderer.drawVolume); return result; } return false; } /** * Returns a clone of the renderer. * * @return A clone. * * @throws CloneNotSupportedException if the renderer cannot be cloned. */ public Object clone() throws CloneNotSupportedException { return super.clone(); } /** * 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.writePaint(this.upPaint, stream); SerialUtilities.writePaint(this.downPaint, 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.upPaint = SerialUtilities.readPaint(stream); this.downPaint = SerialUtilities.readPaint(stream); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -