Not seeing XY points from chartMouseClicked event

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
Fred
Posts: 38
Joined: Sat Dec 12, 2015 4:57 pm
antibot: No, of course not.

Not seeing XY points from chartMouseClicked event

Post by Fred » Wed Dec 16, 2015 5:34 pm

Hello.. I've got a chart mouse listener and though it fires the getDomainCrosshairValue and getRangeCrosshairValue methods return 0.0 always.
I know there could be a delay if the chart has not been updated but the value is always 0.0.

Now this is just a test piece of code that I will take concepts going forward with. Its a collection of stuff that I've found and stuff I've added.
The data is rendered to a XYItemRenderer using XY points, placing shapes at those points on a chart. Ultimately, what I want to do is that when
the mouseclicked event occurs I want to display on the chart at that location the XY values (start or end point) and indicate its matched pair (either start or end point). There will be a unique symbol (shape) that will identify (on the legend) whether it is a stop or end point. I've copied the entire code so you
could quickly ingest into Eclipse or Netbeans and see the results.

Thanks
Fred

Code: Select all

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.LegendItem;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.block.GridArrangement;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.panel.CrosshairOverlay;
import org.jfree.chart.plot.Crosshair;
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.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.ui.RectangleEdge;
import org.jfree.util.ShapeUtilities;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYZDataset;
import org.jfree.chart.title.LegendTitle;

public class MultipleShapesDemo extends JFrame implements ChartMouseListener{
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	   
    public MultipleShapesDemo(String s) {
        super(s);
        //final ChartPanel chartPanel = createGraphPanel();
        JFrame frame = new JFrame(s);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        double[] xValues = {1, 2, 3, 4, 5, 6, 7, 8};
        double[] yValues = {20, 1, 18, 8, 11, 17, 14, 17};
        double[] zValues = {0, 1, 2, 3, 4, 5, 6, 7};
        
        DefaultXYZDataset dataset = new DefaultXYZDataset();
        double[][] data = new double[3][];
        
        data[0] = xValues;
        data[1] = yValues;
        data[2] = zValues;
        dataset.addSeries("Series 1", data);
                
        XYItemRenderer r = (XYItemRenderer) new XYZShapeRenderer();
        NumberAxis xAxis = new NumberAxis("x");
        NumberAxis yAxis = new NumberAxis("y");
        
        final XYPlot plot = new XYPlot(dataset, xAxis, yAxis, r);
        plot.setDomainCrosshairVisible(true); 
        plot.setDomainCrosshairLockedOnData(true); 
        plot.setRangeCrosshairVisible(true); 
        plot.setRangeCrosshairLockedOnData(true); 
        NumberAxis domain = (NumberAxis) plot.getDomainAxis();
        domain.setRange(0.0, 10.0);
        domain.setTickUnit(new NumberTickUnit(0.5));
        //domain.setVerticalTickLabels(true);
        NumberAxis range = (NumberAxis) plot.getRangeAxis();
        range.setRange(0.0, 25.0);
        range.setTickUnit(new NumberTickUnit(2.0));

       final JFreeChart chart = new JFreeChart(s, new Font("Tahoma",0,18), plot, false);
       LegendTitle legendTitle = new LegendTitle(plot, new GridArrangement(4, 2), new GridArrangement(4, 2));
       legendTitle.setPosition(RectangleEdge.BOTTOM);
       chart.addLegend(legendTitle);
       final ChartPanel chartPanel = new ChartPanel(chart);
       this.add(chartPanel, BorderLayout.CENTER);

        // add click event
        chartPanel.addChartMouseListener(new ChartMouseListener() {
            @Override
            public void chartMouseClicked(ChartMouseEvent e) {
                System.out.println("Click event!");
                XYPlot xyPlot3 = chart.getXYPlot();
                System.out.println(xyPlot3.getDomainCrosshairValue() + " " +
                				   xyPlot3.getRangeCrosshairValue());
                XYPlot xyPlot2 = chartPanel.getChart().getXYPlot();
                  // Problem: the coordinates displayed are the one of the previously selected point !
                System.out.println(xyPlot2.getDomainCrosshairValue() + " "
                        + xyPlot2.getRangeCrosshairValue());
            }

            @Override
            public void chartMouseMoved(ChartMouseEvent e) {
            	System.out.println("Mouse Moved Event!");
            }
        });
        
        //frame.setContentPane(new ChartPanel(chart));
        //frame.pack();
        //frame.setVisible(true);       
    }
	
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
    	      MultipleShapesDemo newChart = new MultipleShapesDemo("ChartMouseListener test");
              newChart.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              newChart.pack();
              newChart.setLocationRelativeTo(null);
              newChart.setVisible(true);
              //frame.setContentPane(new ChartPanel(newChart));
              }
        });
    }
    static class XYZShapeRenderer extends AbstractXYItemRenderer{
        /**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		Shape [] shapes = createStandardSeriesShapes();
        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) {
    
            Color[] sColors = {Color.blue,Color.green,Color.red,Color.black,Color.orange};
            Shape hotspot = null;
            EntityCollection entities = null;
            if (info != null) {
                entities = info.getOwner().getEntityCollection();
            }

            double x = dataset.getXValue(series, item);
            double y = dataset.getYValue(series, item);
            //System.out.println("series="+series+" item="+item);
            
            if (Double.isNaN(x) || Double.isNaN(y)) {
                // can't draw anything
                return;
            }
    
            double transX = domainAxis.valueToJava2D(x, dataArea,
                    plot.getDomainAxisEdge());
            double transY = rangeAxis.valueToJava2D(y, dataArea,
                    plot.getRangeAxisEdge());
    
            PlotOrientation orientation = plot.getOrientation();
            boolean useDefaultShape = true;
            Shape shape = null;
            Color color = Color.cyan;
            if(dataset instanceof XYZDataset){
                XYZDataset xyz = (XYZDataset)dataset;
                double z = xyz.getZValue(series, item);
                if(z == 0){
                    shape = shapes[7];
                    color = sColors[0];
                    useDefaultShape = false;
                }
                if(z == 1){
                    shape = shapes[1];
                    color = sColors[1];
                    useDefaultShape = false;
                }
                if(z == 2){
                    shape = shapes[2];
                    color = sColors[2];
                    useDefaultShape = false;
                }
                if(z == 3){
                    shape = shapes[3];
                    color = sColors[3];
                    useDefaultShape = false;
                }
                if(z == 4){
                    shape = shapes[4];
                    color = sColors[4];
                    useDefaultShape = false;
                }
                if(z == 5){
                    shape = shapes[5];
                    color = sColors[0];
                    useDefaultShape = false;
                }
                if(z == 6){
                    shape = shapes[6];
                    color = sColors[1];
                    useDefaultShape = false;
                }
            }
            
            if(useDefaultShape){
                shape = getItemShape(series, item);
            }
            if (orientation == PlotOrientation.HORIZONTAL) {
                shape = ShapeUtilities.createTranslatedShape(shape, transY,
                        transX);
            }
            else if (orientation == PlotOrientation.VERTICAL) {
                shape = ShapeUtilities.createTranslatedShape(shape, transX,
                        transY);
            }
            hotspot = shape;
            if (shape.intersects(dataArea)) {
                    //if (getItemShapeFilled(series, item)) {
                        g2.setPaint(lookupSeriesPaint(series));
                        g2.fill(shape);
                   //}
                g2.setPaint(getItemOutlinePaint(series, item));
                g2.setStroke(getItemOutlineStroke(series, item));
                g2.draw(shape);
            }
    
            // add an entity for the item...
            if (entities != null) {
        		LegendItemCollection oldLegend = plot.getLegendItems();
        		//System.out.println("color="+color);
        		plot.getRenderer().setSeriesPaint(0, color);
         		LegendItem legenditem0 = new LegendItem("", "-", "place holder"+series, null, shapes[0], Color.white);
        		LegendItem legenditem1 = new LegendItem("Start", "-", "start point series="+series, null, shapes[7], color);
        		LegendItem legenditem2 = new LegendItem("Stop", "-", "end point series="+series, null, shapes[3], color);
        		LegendItem legenditem3 = new LegendItem("Start", "-", "start point series="+series, null, shapes[0], Color.red);
        		LegendItem legenditem4 = new LegendItem("Stop", "-", "end point series="+series, null, shapes[4], Color.red);
        		boolean check4Legend = IsLegendDefined(oldLegend,legenditem1);
        		if (!check4Legend){
        			System.out.println("legenditem1..NOT found..");
            		oldLegend.add(legenditem0);
            		oldLegend.add(legenditem1);
            		oldLegend.add(legenditem2);
                	oldLegend.add(legenditem3);
                	oldLegend.add(legenditem4);
            		plot.setFixedLegendItems(oldLegend);
        		}
        		addEntity(entities, hotspot, dataset, series, item, transX,transY);
            }
        }
    }
   
    private static boolean IsLegendDefined(LegendItemCollection oldLegend, LegendItem newLegend){
    	boolean rtnVal = false;
    	int oldLegendCnt = oldLegend.getItemCount();
    	String newTT = newLegend.getToolTipText();
    	//System.out.println("legendCount="+oldLegendCnt);
        for (int j = 0; j < oldLegendCnt; j++) {
        	LegendItem testLI = oldLegend.get(j);
        	String oldTT = testLI.getToolTipText();
        	//System.out.println("oldTT="+oldTT);
        	//System.out.println("newTT="+newTT);
        	if (oldTT == null){
        		continue;
        	} else	if (oldTT.compareTo(newTT) == 0){
        		        rtnVal = true;
        		        //System.out.println("exiting loop...");
        		        break;
        	        }
            }
		    return rtnVal;
    	 
    }
    
 
    /**
      * Creates an array of standard shapes to display for the items in series 
      * on charts.
      *
      * @return The array of shapes.
      */    
       public static Shape[] createStandardSeriesShapes() {

           Shape[] result = new Shape[10];

           double size = 6.0;
           double delta = size / 2.0;
           int[] xpoints = null;
           int[] ypoints = null;

           // square
           result[0] = new Rectangle2D.Double(-delta, -delta, size, size);
           // circle
           result[1] = new Ellipse2D.Double(-delta, -delta, size, size);

           // up-pointing triangle
           xpoints = intArray(0.0, delta, -delta);
           ypoints = intArray(-delta, delta, delta);
           result[2] = new Polygon(xpoints, ypoints, 3);

           // diamond
           xpoints = intArray(0.0, delta, 0.0, -delta);
           ypoints = intArray(-delta, 0.0, delta, 0.0);
           result[3] = new Polygon(xpoints, ypoints, 4);

           // horizontal rectangle
           result[4] = new Rectangle2D.Double(-delta, -delta / 2, size, size / 2);

           // down-pointing triangle
           xpoints = intArray(-delta, +delta, 0.0);
           ypoints = intArray(-delta, -delta, delta);
           result[5] = new Polygon(xpoints, ypoints, 3);

           // horizontal ellipse
           result[6] = new Ellipse2D.Double(-delta, -delta / 2, size, size / 2);

           // right-pointing triangle
           xpoints = intArray(-delta, delta, -delta);
           ypoints = intArray(-delta, 0.0, delta);
           result[7] = new Polygon(xpoints, ypoints, 3);

           // vertical rectangle
           result[8] = new Rectangle2D.Double(-delta / 2, -delta, size / 2, size);

           // left-pointing triangle
           xpoints = intArray(-delta, delta, delta);
           ypoints = intArray(0.0, -delta, +delta);
           result[9] = new Polygon(xpoints, ypoints, 3);

           return result;

       }

  /**
    * Helper method to avoid lots of explicit casts in getShape().  Returns
    * an array containing the provided doubles cast to ints.
    *
    * @param a  x
    * @param b  y
    * @param c  z
    *
    * @return int[3] with converted params.
    */
      private static int[] intArray(double a, double b, double c) {
          return new int[] {(int) a, (int) b, (int) c};
      }
      /**
        * Helper method to avoid lots of explicit casts in getShape().  Returns
        * an array containing the provided doubles cast to ints.
        *
        * @param a  x
        * @param b  y
        * @param c  z
        * @param d  t
        *
        * @return int[4] with converted params.
        */
      private static int[] intArray(double a, double b, double c, double d) {
             return new int[] {(int) a, (int) b, (int) c, (int) d};
      }

	@Override
	public void chartMouseClicked(ChartMouseEvent event) {
		// Mouse events defined within the MultipleShapesDemo Constructor
		
	}

	@Override
	public void chartMouseMoved(ChartMouseEvent event) {
		// Mouse events defined within the MultipleShapesDemo Constructor
	}
}

Naxter
Posts: 45
Joined: Thu Jun 26, 2014 8:24 am
antibot: No, of course not.
Location: Germany, Aachen

Re: Not seeing XY points from chartMouseClicked event

Post by Naxter » Thu Dec 17, 2015 8:22 am

hey,

have you tried using the

Code: Select all

e.getChart()
to get the points?

Locked