itemlabel for HighLowChart (and image labels)

Discussion about JFreeChart related to stockmarket charts.
Locked
dmitryx
Posts: 6
Joined: Thu Dec 13, 2007 6:27 pm

itemlabel for HighLowChart (and image labels)

Post by dmitryx » Thu Dec 13, 2007 6:38 pm

Hi. I'm trying to generate labels on highlow chart with OHLC dataset. I'm using HighLowItemLabelGenerator and there are no labels on chart.
Is there any way to put labels on HighLowChart?
Besides, i want to put labels only for spesific Items. How do i do that? Also, is there any way to put image as ItemLabel?
Thank you.

dmitryx
Posts: 6
Joined: Thu Dec 13, 2007 6:27 pm

Post by dmitryx » Mon Dec 17, 2007 11:36 am

Forum is dead, or what?
Maybe, administrators could answer, for i paid for documentation (which sucks in many ways, btw), and everything it says is "some of ItemLabelGenerators are not implemented", without specifying exactly list of generators which were not implemented yet.
It seems like renderer (HighLowRenderer) doesnt call generateLabel method. Is it my mistake, or its not working yet? Is there anybody who done that before? I could try to do it again, but what the point in spending my time, if its not implemented or something?

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Mon Dec 17, 2007 9:38 pm

dmitryx wrote:...i paid for documentation (which sucks in many ways, btw)...
Please send me your transaction reference and I'll refund your purchase.

HighLowRenderer is one of the renderers that doesn't yet support item labels.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

dmitryx
Posts: 6
Joined: Thu Dec 13, 2007 6:27 pm

Post by dmitryx » Mon Dec 17, 2007 9:46 pm

I'm not trying to get my money back and i'm satisfied with product, and without doc its almost useles, as your policy is to make people to buy docs (which is ok in general), but even after, to make something in any way "complex" work - we need to spend our time or pay for support (and i dont need year support to solve one problem), for something is missed in devguide.

dmitryx
Posts: 6
Joined: Thu Dec 13, 2007 6:27 pm

Post by dmitryx » Mon Dec 17, 2007 9:48 pm

and thank you.
i'm not that rude. and i didnt try to offence or anything.

dmitryx
Posts: 6
Joined: Thu Dec 13, 2007 6:27 pm

Post by dmitryx » Mon Dec 17, 2007 9:53 pm

and there is no way to make itemlabel from image?

---
i'm thinking of putting colorless (the same as background) LineChart on the same place with labels. maybe it will work. i'll write here the results for those who will face the same problem.

dmitryx
Posts: 6
Joined: Thu Dec 13, 2007 6:27 pm

Post by dmitryx » Mon Dec 17, 2007 10:48 pm

Workaround with LineChart is working.

javageek
Posts: 11
Joined: Tue Apr 14, 2009 2:26 pm

Re: itemlabel for HighLowChart (and image labels)

Post by javageek » Tue Apr 14, 2009 3:58 pm

Hey dmitryx, what you have done may work for something I am trying to accomplish. I need to place text and/or symbols at specific spots on a chart. Please post your code.

Is it possible to, instead of text, have it pick up an image file (gif, jpg, etc) and place it where the text would go?

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: itemlabel for HighLowChart (and image labels)

Post by david.gilbert » Wed Apr 15, 2009 9:47 am

You can use XYTextAnnotation and/or XYImageAnnotation. Something that isn't supported yet, but would be a useful extension to JFreeChart, is an annotation that can be attached to a specific data item (rather than just an XY location) so that if/when the data item is updated, the annotation "follows" it. Just mentioning it, I don't know if you need that or not.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

lozsui
Posts: 2
Joined: Sun Feb 19, 2012 1:06 am
antibot: No, of course not.
Location: Zurich

Re:

Post by lozsui » Sun Feb 19, 2012 1:34 am

david.gilbert wrote:HighLowRenderer is one of the renderers that doesn't yet support item labels.
How does one have to implement that? Is there another renderer where one could pinch an idea how to do it?

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: itemlabel for HighLowChart (and image labels)

Post by david.gilbert » Sun Feb 19, 2012 9:36 pm

You could look at the way it is implemented in XYLineAndShapeRenderer:

1195 // draw the item label if there is one...
1196 if (isItemLabelVisible(series, item)) {
1197 drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
1198 (y1 < 0.0));
1199 }

I'm not sure what is the right way to handle the high and low values, particularly ensuring that the item labels don't overlap with the visual representation of these values.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

lozsui
Posts: 2
Joined: Sun Feb 19, 2012 1:06 am
antibot: No, of course not.
Location: Zurich

Re: itemlabel for HighLowChart (and image labels)

Post by lozsui » Fri Feb 24, 2012 12:34 pm

david.gilbert wrote:You could look at the way it is implemented in XYLineAndShapeRenderer:

1195 // draw the item label if there is one...
1196 if (isItemLabelVisible(series, item)) {
1197 drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
1198 (y1 < 0.0));
1199 }

I'm not sure what is the right way to handle the high and low values, particularly ensuring that the item labels don't overlap with the visual representation of these values.
Here comes how I implemented the input mentioned above. It is more a beginning than a fully fledged example of how to include labels in HighLowCharts.

Code: Select all

/* 
 * Some parts of this example are copied from HighLowChartDemo1.java.
 */

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.labels.StandardXYItemLabelGenerator;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.HighLowRenderer;
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.data.xy.DefaultHighLowDataset;
import org.jfree.data.xy.OHLCDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;


/**
 * A demo showing a high-low-open-close chart.
 */
public class HLOCChartWithOwnRendering2 extends ApplicationFrame {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
     * A demonstration application showing a high-low-open-close chart.
     *
     * @param title  the frame title.
     */
    public HLOCChartWithOwnRendering2(String title) {
        super(title);
        JPanel chartPanel = createDemoPanel();
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(chartPanel);
    }

    private static JFreeChart createChart(OHLCDataset dataset) {
        JFreeChart chart = ChartFactory.createHighLowChart(
                "High-Low-Open-Close Demo", "Time", "Price", dataset, true);
        XYPlot plot = (XYPlot) chart.getPlot();
        
        // plug in my own renderer
        plot.setRenderer(new MyHighLowRenderer2());
        MyHighLowRenderer2 r = (MyHighLowRenderer2) plot.getRenderer();
        r.setHLOCItemPaint(Color.black);
        
        // To set Labels
        XYItemLabelGenerator generator = new StandardXYItemLabelGenerator();
        r.setBaseItemLabelGenerator(generator);
        r.setBaseItemLabelsVisible(true);
        
        DateAxis axis = (DateAxis) plot.getDomainAxis();
        axis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
        yAxis.setNumberFormatOverride(new DecimalFormat("$0.00"));
        
        return chart;
    }

    private static final Calendar calendar = Calendar.getInstance();

    /**
     * Returns a date using the default locale and timezone.
     *
     * @param y  the year (YYYY).
     * @param m  the month (1-12).
     * @param d  the day of the month.
     * @param hour  the hour of the day.
     * @param min  the minute of the hour.
     *
     * @return A date.
     */
    private static Date createDate(int y, int m, int d, int hour, int min) {
        calendar.clear();
        calendar.set(y, m - 1, d, hour, min);
        return calendar.getTime();
    }

    /**
     * Creates a sample high low dataset.
     *
     * @return a sample high low dataset.
     */
    public static OHLCDataset createDataset() {

        Date[] date = new Date[14];
        double[] high = new double[14];
        double[] low = new double[14];
        double[] open = new double[14];
        double[] close = new double[14];
        double[] volume = new double[14];

        int jan = 1;

        date[0]  = createDate(2001, jan, 4, 12, 0);
        high[0]  = 54.00;
        low[0]   = 51.00;
        open[0]  = 52.00;
        close[0] = 53.00;
        volume[0] = 100.0;
        
        date[1]  = createDate(2001, jan, 5, 12, 0);
        high[1]  = 56.50;
        low[1]   = 51.80;
        open[1]  = 53.50;
        close[1] = 56.00;
        volume[1] = 150.0;

        date[2]  = createDate(2001, jan, 6, 12, 0);
        high[2]  = 57.00;
        low[2]   = 52.00;
        open[2]  = 56.00;
        close[2] = 54.50;
        volume[2] = 70.0;

        date[3]  = createDate(2001, jan, 7, 12, 0);
        high[3]  = 58.00;
        low[3]   = 54.00;
        open[3]  = 54.50;
        close[3] = 57.50;
        volume[3] = 200.0;

        date[4]  = createDate(2001, jan, 8, 12, 0);
        high[4]  = 58.50;
        low[4]   = 55.00;
        open[4]  = 57.50;
        close[4] = 55.50;
        volume[4] = 120.0;

        date[5]  = createDate(2001, jan, 9, 12, 0);
        high[5]  = 57.80;
        low[5]   = 53.00;
        open[5]  = 56.00;
        close[5] = 53.00;
        volume[5] = 110.0;

        date[6]  = createDate(2001, jan, 10, 12, 0);
        high[6]  = 55.0;
        low[6]   = 51.50;
        open[6]  = 53.50;
        close[6] = 54.00;
        volume[6] = 20.0;

        date[7]  = createDate(2001, jan, 11, 12, 0);
        high[7]  = 54.50;
        low[7]   = 51.80;
        open[7]  = 54.00;
        close[7] = 52.00;
        volume[7] = 30.0;

        date[8]  = createDate(2001, jan, 12, 12, 0);
        high[8]  = 52.50;
        low[8]   = 49.00;
        open[8]  = 52.00;
        close[8] = 51.70;
        volume[8] = 100.0;

        date[9]  = createDate(2001, jan, 13, 12, 0);
        high[9]  = 52.00;
        low[9]   = 48.90;
        open[9]  = 51.00;
        close[9] = 49.00;
        volume[9] = 50.0;

        date[10]  = createDate(2001, jan, 14, 12, 0);
        high[10]  = 49.30;
        low[10]   = 46.00;
        open[10]  = 49.00;
        close[10] = 46.00;
        volume[10] = 80.0;

        date[11]  = createDate(2001, jan, 15, 12, 0);
        high[11]  = 47.10;
        low[11]   = 45.90;
        open[11]  = 46.00;
        close[11] = 47.00;
        volume[11] = 90.0;

        date[12]  = createDate(2001, jan, 16, 12, 0);
        high[12]  = 47.10;
        low[12]   = 44.90;
        open[12]  = 46.80;
        close[12] = 45.00;
        volume[12] = 20.0;

        date[13]  = createDate(2001, jan, 17, 12, 0);
        high[13]  = 46.80;
        low[13]   = 43.10;
        open[13]  = 45.20;
        close[13] = 44.50;
        volume[13] = 70.0;

        return new DefaultHighLowDataset("Series 1", date, high, low, open, close, volume);

    }

    /**
     * Creates a panel for the demo (used by SuperDemo.java).
     *
     * @return A panel.
     */
    public static JPanel createDemoPanel() {
        JFreeChart chart = createChart(createDataset());
        return new ChartPanel(chart);
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        HLOCChartWithOwnRendering2 demo = new HLOCChartWithOwnRendering2(
                "JFreeChart: HighLowChartDemo1.java");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}

class MyHighLowRenderer2 extends HighLowRenderer {
	
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
    /**
     * The paint used for the the HLOC-Items (modification).
     */
    private transient Paint hlocItemPaint;
    
    /**
     * The paint used for the open ticks (if <code>null</code>, the series
     * paint is used instead).
     */
    private transient Paint openTickPaint;

    /**
     * The paint used for the close ticks (if <code>null</code>, the series
     * paint is used instead).
     */
    private transient Paint closeTickPaint;
	
    /**
     * Newly introduced method.
     * 
     * Returns the paint used to draw the HLOC items.
     *
     * @return The paint used to draw the HLOC items.
     *
     * @see #setHLOCItemPaint(Paint)
     */
    public Paint getHLOCItemPaint() {
        return this.hlocItemPaint;
    }

    /**
     * Newly introduced method.
     * 
     * Sets the paint used to draw HLOC items and sends a
     * {@link RendererChangeEvent} to all registered listeners.
     *
     * @param paint  the paint (<code>null</code> permitted).
     *
     * @see #getHLOCPaint()
     */
    public void setHLOCItemPaint(Paint paint) {
        this.hlocItemPaint = paint;
        fireChangeEvent();
    }
    
	/**
     * Overwritten version of jfree.org.
     *
     * @param g2  the graphics device.
     * @param state  the renderer state.
     * @param dataArea  the area within which the plot is being drawn.
     * @param info  collects information 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) {

        double x = dataset.getXValue(series, item);
        if (!domainAxis.getRange().contains(x)) {
            return;    // the x value is not within the axis range
        }
        double xx = domainAxis.valueToJava2D(x, dataArea,
                plot.getDomainAxisEdge());

        // setup for collecting optional entity info...
        Shape entityArea = null;
        EntityCollection entities = null;
        if (info != null) {
            entities = info.getOwner().getEntityCollection();
        }

        PlotOrientation orientation = plot.getOrientation();
        RectangleEdge location = plot.getRangeAxisEdge();

        Paint itemPaint = getItemPaint(series, item);
        // if-block is a modification of jfree.org version.
        if (this.hlocItemPaint != null) {
        	itemPaint = this.hlocItemPaint;
        }
        Stroke itemStroke = getItemStroke(series, item);
        g2.setPaint(itemPaint);
        g2.setStroke(itemStroke);

        if (dataset instanceof OHLCDataset) {
            OHLCDataset hld = (OHLCDataset) dataset;

            double yHigh = hld.getHighValue(series, item);
            double yLow = hld.getLowValue(series, item);
            if (!Double.isNaN(yHigh) && !Double.isNaN(yLow)) {
                double yyHigh = rangeAxis.valueToJava2D(yHigh, dataArea,
                        location);
                double yyLow = rangeAxis.valueToJava2D(yLow, dataArea,
                        location);
                if (orientation == PlotOrientation.HORIZONTAL) {
                    g2.draw(new Line2D.Double(yyLow, xx, yyHigh, xx));
                    entityArea = new Rectangle2D.Double(Math.min(yyLow, yyHigh),
                            xx - 1.0, Math.abs(yyHigh - yyLow), 2.0);
                }
                else if (orientation == PlotOrientation.VERTICAL) {
                    g2.draw(new Line2D.Double(xx, yyLow, xx, yyHigh));
                    entityArea = new Rectangle2D.Double(xx - 1.0,
                            Math.min(yyLow, yyHigh), 2.0,
                            Math.abs(yyHigh - yyLow));
                }
            }

            double delta = getTickLength();
            if (domainAxis.isInverted()) {
                delta = -delta;
            }
            if (getDrawOpenTicks()) {
                double yOpen = hld.getOpenValue(series, item);
                if (!Double.isNaN(yOpen)) {
                    double yyOpen = rangeAxis.valueToJava2D(yOpen, dataArea,
                            location);
                    if (this.openTickPaint != null) {
                        g2.setPaint(this.openTickPaint);
                    }
                    else {
                        g2.setPaint(itemPaint);
                    }
                    if (orientation == PlotOrientation.HORIZONTAL) {
                        g2.draw(new Line2D.Double(yyOpen, xx + delta, yyOpen,
                                xx));
                    }
                    else if (orientation == PlotOrientation.VERTICAL) {
                        g2.draw(new Line2D.Double(xx - delta, yyOpen, xx,
                                yyOpen));
                    }
                }
            }

            if (getDrawCloseTicks()) {
                double yClose = hld.getCloseValue(series, item);
                if (!Double.isNaN(yClose)) {
                    double yyClose = rangeAxis.valueToJava2D(
                        yClose, dataArea, location);
                    if (this.closeTickPaint != null) {
                        g2.setPaint(this.closeTickPaint);
                    }
                    else {
                        g2.setPaint(itemPaint);
                    }
                    if (orientation == PlotOrientation.HORIZONTAL) {
                        g2.draw(new Line2D.Double(yyClose, xx, yyClose,
                                xx - delta));
                    }
                    else if (orientation == PlotOrientation.VERTICAL) {
                        g2.draw(new Line2D.Double(xx, yyClose, xx + delta,
                                yyClose));
                    }
                }
            }

        }
        else {
            // not a HighLowDataset, so just draw a line connecting this point
            // with the previous point...
            if (item > 0) {
                double x0 = dataset.getXValue(series, item - 1);
                double y0 = dataset.getYValue(series, item - 1);
                double y = dataset.getYValue(series, item);
                if (Double.isNaN(x0) || Double.isNaN(y0) || Double.isNaN(y)) {
                    return;
                }
                double xx0 = domainAxis.valueToJava2D(x0, dataArea,
                        plot.getDomainAxisEdge());
                double yy0 = rangeAxis.valueToJava2D(y0, dataArea, location);
                double yy = rangeAxis.valueToJava2D(y, dataArea, location);
                if (orientation == PlotOrientation.HORIZONTAL) {
                    g2.draw(new Line2D.Double(yy0, xx0, yy, xx));
                }
                else if (orientation == PlotOrientation.VERTICAL) {
                    g2.draw(new Line2D.Double(xx0, yy0, xx, yy));
                }
            }
        }

        if (entities != null) {
            addEntity(entities, entityArea, dataset, series, item, 0.0, 0.0);
        }
        
    	/* The following if-Block is more or less a quick and dirty copy and past of
    	 * some code out of function drawSecondaryPass out of class XYLineAndShapeRenderer (Version 1.0.13).
    	 * The code in the if block does not exist in HighLowRenderer.
    	 * */
    	if (isItemLabelVisible(series, item)) {
            // get the data point...
            double x1 = dataset.getXValue(series, item);
            double y1 = dataset.getYValue(series, item);
            if (Double.isNaN(y1) || Double.isNaN(x1)) {
                return;
            }
            RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
            RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
            double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
            double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
        	
            xx = transX1;
            double yy = transY1;
            yy = 100.0;
            System.out.println(xx+" "+yy);
    		drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
    				(y1 < 0.0));
    	}
    }
}

Selinajone
Posts: 1
Joined: Mon May 07, 2012 11:04 am
antibot: No, of course not.
Contact:

Re: itemlabel for HighLowChart (and image labels)

Post by Selinajone » Mon May 07, 2012 11:08 am

People here seem to quite, the reason that I into this BBS, is want to learn some knowledge in this aspect.

loco
Posts: 1
Joined: Sun Jun 02, 2013 2:54 pm
antibot: No, of course not.

Re: itemlabel for HighLowChart (and image labels)

Post by loco » Sun Jun 02, 2013 2:59 pm

princelee1019 wrote:It seems like renderer doesnt call generateLabel method. Is it my mistake, or its not working yet? Is there anybody who done that before? I could try to do it again, but what the point in spending my time, if its not implemented or something?
As far as I know item labels are not supported by HighLowRenderer.

ElliElie789
Posts: 1
Joined: Fri Nov 01, 2013 11:34 am
antibot: No, of course not.

Re: itemlabel for HighLowChart (and image labels)

Post by ElliElie789 » Fri Nov 01, 2013 11:38 am

Thanks for sharing.

Locked