CustomXYToolTipGenerator fails with Custom Renderer

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
jyoshimi
Posts: 2
Joined: Sat Oct 20, 2012 11:42 pm
antibot: No, of course not.

CustomXYToolTipGenerator fails with Custom Renderer

Post by jyoshimi » Sat Oct 20, 2012 11:53 pm

Hello,

When I use a custom renderer to render the points in a Scatter Plot, it prevents a CustomXYToolTipGenerator from working. I've posted some sample code below. To see the problem, go to where "***" is and comment that line out. Then the tooltips work. But when the custom renderer is added they no longer work.

I am using jfreechart-1.0.14.jar and jcommon-1.0.17.jar with java 7 on on Mac running OS X lion (10.7.4).

Code: Select all

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.CustomXYToolTipGenerator;
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.AbstractXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleEdge;

public class ChartExample {
	
    private static class CustomRenderer extends AbstractXYItemRenderer {

		@Override
		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) {

	        // do nothing if item is not visible
	        if (!getItemVisible(series, item)) {
	            return;
	        }
	        
	        int dotSize = 10;

	        // get the data point...
	        double x = dataset.getXValue(series, item);
	        double y = dataset.getYValue(series, item);
	        double adjx = (dotSize - 1) / 2.0;
	        double adjy = (dotSize - 1) / 2.0;
	        if (!Double.isNaN(y)) {
	            RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
	            RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
	            double transX = domainAxis.valueToJava2D(x, dataArea,
	                    xAxisLocation) - adjx;
	            double transY = rangeAxis.valueToJava2D(y, dataArea, yAxisLocation)
	                    - adjy;

	            g2.setPaint(getItemPaint(series, item));
	            PlotOrientation orientation = plot.getOrientation();
	            if (orientation == PlotOrientation.HORIZONTAL) {
	                g2.fillOval((int) transY, (int) transX, dotSize,
	                        dotSize);
	            }
	            else if (orientation == PlotOrientation.VERTICAL) {
	                g2.fillOval((int) transX, (int) transY, dotSize,
	                        dotSize);
	            }

	            int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
	            int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
	            updateCrosshairValues(crosshairState, x, y, domainAxisIndex,
	                    rangeAxisIndex, transX, transY, orientation);
	        }			
		}
    }
    
    private static class CustomToolTipGenerator extends CustomXYToolTipGenerator {
        @Override
        public String generateToolTip(XYDataset data, int series, int item) {
            return data.getXValue(series, item) + "," + data.getYValue(series, item) ;
        }
    }
    
    public static void main(String[] args) {

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(new XYSeries("Data", false, true));
        for(int i = 0; i < 10; i++) {
        	dataset.getSeries(0).add(i,i);
        	dataset.getSeries(0).add(10 - i,i);
        }
        
        JFreeChart chart = ChartFactory.createScatterPlot("Test",
                "X", "Y", dataset,
                PlotOrientation.VERTICAL, false, true, false);
        
        CustomRenderer renderer = new CustomRenderer();
        chart.getXYPlot().setRenderer(renderer); // *** Comment this out and tooltips work
                
        CustomToolTipGenerator generator = new CustomToolTipGenerator();
        chart.getXYPlot().getRenderer().setSeriesToolTipGenerator(0, generator);
        
    	JFrame frame = new JFrame();
        ChartPanel panel = new ChartPanel(chart);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);


    }

}
Thanks for any advice!

- Jeff

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: CustomXYToolTipGenerator fails with Custom Renderer

Post by John Matthews » Sun Oct 21, 2012 12:34 am

Your CustomRenderer lacks entity support, required for tool tips, IIUC. You can change the Shape, as shown below. There's a related example here.

Code: Select all

chart.getXYPlot().getRenderer().setSeriesShape(0, new Ellipse2D.Double(-5, -5, 10, 10));

jyoshimi
Posts: 2
Joined: Sat Oct 20, 2012 11:42 pm
antibot: No, of course not.

Re: CustomXYToolTipGenerator fails with Custom Renderer

Post by jyoshimi » Mon Oct 22, 2012 7:04 am

Thanks John. I need a custom renderer for other reasons in my app (which were not there in the sample code). The custom shapes weren't working before but I had been using the XYDotRenderer instead of the XYLineAndShapeRenderer. Using your code with a custom renderer that extends XYLineAndShapeRenderer did the trick, presumably because the XYLineAndShapeRenderer provides entity support (though I admit I don't even know what "entity support" is). Anyway, everything's working now so thanks again.

- Jeff

Locked