JFreeChart : obtain data source value on mouse click
Asked Answered
M

2

7

I have a JFreeChart instance that displays process memory status, initialized as follows:

m_data = new TimeSeriesCollection();
TimeSeries vmsize = new TimeSeries("VMSize");
TimeSeries resident = new TimeSeries("Resisdent");
TimeSeries shared = new TimeSeries("Shared memory");
TimeSeries code = new TimeSeries("Code");
TimeSeries data = new TimeSeries("Data");
m_data.addSeries(vmsize);
m_data.addSeries(resident);
m_data.addSeries(shared);
m_data.addSeries(code);
m_data.addSeries(data);
JFreeChart chart = ChartFactory.createTimeSeriesChart("Memory usage", "Time", "Size", m_data, true, true, false);
m_chart = new ChartPanel(chart);

Later I add values to each TimeSeries in the TimeSeriesCollection. I would like to somehow know - when the user clicks on the Chart - either what time associated with that columm, or even better - what is the index of the value.

I looked at the JFreeChart and ChartMouseListener classes, but I could not figure out how to do that (also the documentation of JFreeChart is annoyingly scarce, I guess they are trying to get people to buy their developer's guide).

Missionary answered 22/7, 2010 at 12:44 Comment(0)
S
3

if you click dead on the item, the event.getEntity() function returns XYItem and then from there onwards

XYItemEntity xyitem=(XYItemEntity) event.getEntity(); // get clicked entity
XYDataset dataset = (XYDataset)xyitem.getDataset(); // get data set
System.out.println(xyitem.getItem()+" item of "+xyitem.getSeriesIndex()+"series");
System.out.println(dataset.getXValue(xyitem.getSeriesIndex(), xyitem.getItem()));
System.out.println(dataset.getYValue(xyitem.getSeriesIndex(), xyitem.getItem()));
Comparable comparable=dataset.getSeriesKey(0);
XYPlot xyplot = (XYPlot) event.getChart().getPlot();
System.out.println(xyplot.getRangeCrosshairValue());

however incase you do not click on the item itself but your crosshair is set to auto lock on data, in such case the crosshair will move to nearest item but since the item has not been clicked, you will not be able to get the XYItem and hence you cannot know the series and item index, to solve this problem there is this code below, it should be put in the catch clause while the above mentioned code should be in try clause

first define a function which will take crosshair value at domain and range and also Xydataset, this functions returns an inner class object that groups item index and series index

public static SeriesAndItemIndex getItemIndex(double domainVal,double rangeVal,XYDataset xydataset){
Comparable comparable;
int indexOf;
for(int i=0;i<xydataset.getSeriesCount();i++){

comparable =  xydataset.getSeriesKey(i);
     indexOf=xydataset.indexOf(comparable);
for(int j=0 ; j<xydataset.getItemCount(indexOf);j++){

    double x=xydataset.getXValue(indexOf, j);
    double y=xydataset.getYValue(indexOf, j);

    if(x == domainVal && y==rangeVal){
        return  new SeriesAndItemIndex(j,indexOf);//return item index and series index
                }


            }
        }
        return null;
    }

private static class SeriesAndItemIndex{ ///inner CLASS to group series and item clicked index
        public int itemIndex;
        public int seriesIndex;
        public SeriesAndItemIndex(int i,int s){
            itemIndex=i;
            seriesIndex=s;
        }

        @Override
        public String toString(){
            return "itemIndex="+itemIndex+",seriesIndex="+seriesIndex;
        }
    }

how to use it?

try{......code block from the top

}catch(Exception e){

Object source=event.getSource();
JFreeChart chartpanel=(JFreeChart)source;
XYPlot xyplot = (XYPlot) chartpanel.getPlot();
XYDataset xydataset= xyplot.getDataset();
double d=xyplot.getDomainCrosshairValue(); //get crosshair X value
double r =xyplot.getRangeCrosshairValue(); //get crosshair y value
SeriesAndItemIndex index=getItemIndex(d,r,xydataset);
if(index != null){
    System.out.println(index.toString());
}
}
Salami answered 9/5, 2011 at 11:17 Comment(2)
To which event should I register and on which object? I tried ading a change listener to the JFreeChart, but it's event does not have getEntity.Missionary
I think its ChartChangelistner ... something like thatSalami
P
2

hmm should work, if you replace the last two lines by something like this:

ChartPanel panel=new ChartPanel(ChartFactory.createTimeSeriesChart("Memory usage", "Time", "Size", m_data, true, true, false)));
panel.addChartMouseListener(new ChartMouseListener(){
    void chartMouseClicked(ChartMouseEvent e){
        [...do something on click...]
    }
    void chartMouseMoved(ChartMouseEvent e){
        [...do something on move...]
    }
});
return panel;
Pirri answered 22/7, 2010 at 12:57 Comment(3)
Well, I already looked at ChartMouseLIstener, the information in the event is pretty useless. the question is not how to add a listener - but rather how to obtain the relevant data from the event.Missionary
you can use ChartEvent.getEntity() to get the shape (bar,line) under the mouse jfree.org/jfreechart/api/javadoc/org/jfree/chart/entity/…Pirri
Yes, I seen the getShape() API call already. what I am after is the data this shapre represents. the shape itself depends on the zoom and viewport of the chart.Missionary

© 2022 - 2024 — McMap. All rights reserved.