Clicking on Legend

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
benoitx
Posts: 40
Joined: Fri Apr 11, 2003 5:29 pm
Location: London, yes England (where else?)
Contact:

Clicking on Legend

Post by benoitx » Mon Aug 07, 2017 3:56 pm

Hello

I have looked at the HideSeriesDemo1/2/3 and I was wondering if we could achieve something similar by clicking on the legend itself.

https://www.evernote.com/l/AUUxY3xV1LBA ... hWMCcFVAFQ

This is is something quite common with say Highcharts:
* click on the legend for a series and the legend becomes GREY and the series disappears
* click on the legend for a greyed series and it is active again and the series appears.

That way we do not need to add a series of checkboxes.

I tried to look at LegendTitle and add a listener but nothing obvious, any pointers would be very welcome!

Thanks!
Benoit

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Clicking on Legend

Post by paradoxoff » Mon Aug 07, 2017 5:06 pm

It is doable, but will require some effort. Here is an outline of a possible approach:
- Register a ChartMouseListener on the ChartPanel and implement the chartMouseClicked-method.
- The ChartMouseEvent parameter gives you a reference to a ChartEntity and a JFreeChart
- Check whether the ChartEntity is an instance of LegendItemEntity.
- If yes: the LegendItemEntity gives you a reference to a Dataset, a Series Key, and a
- then you can check whether the type of the dataset from the LegendItemEntity and the type of the plot of the JFreeChart match, i.e. whether the Plot is an instanceof CategoryPlot and the dataset an instanceof CategoryDataset or the Plot is an instanceof XYPlot and the dataset an instanceof XYDataset and so on.
- If you have found what type of Plot you are dealing with, you can get a reference of the renderer. For an XYPlot, xyplot.indexOf(XYDataset) gives you the index of the dataset, and xyplot.getRenderer(int index) gives you the renderer. For a CategoryPlot, the approach is the same.
- The dataset and the series key allow you to determine the index of the series, either by calling xydataset.indexOf(seriesKey), or by iterating over the row keys of a CategoryDataset.
- if you have the renderer and the series index, you can get and set the SeriesVisibleInLegend flag and e. g. invert its current value
All of the above should work without writing a new class. At present, invisible series are not included in the legend at all. The legend items are generated by the renderer. If the series is not visible, a null legend item is returned. You wil have to change that behaviour for all renderers that you intend to use. I recommend to have a look at the getLegendItem(int datasetIndex, int series) method of the renderers you would like to use and see how the legend generation is working. For your requirement, setting a grey legend labelPaint, and a null shape should work.

benoitx
Posts: 40
Joined: Fri Apr 11, 2003 5:29 pm
Location: London, yes England (where else?)
Contact:

Re: Clicking on Legend

Post by benoitx » Mon Aug 07, 2017 5:23 pm

A big thank you for your pointers, we are NEARLY there... BUT If I make the series invisible, the LEGEND is also removed...
EVEN is I immediately use setSeriesVisibleInLegend to true.

I'd like the legend to remain (maybe change its colour)...

Why is the legend removed for the invisible series if I set it to visible?

Thanks
Benoit

Code: Select all

    public void chartMouseClicked(final ChartMouseEvent event) {
        final ChartEntity e = event.getEntity();
        if (e != null) {
            if (e instanceof LegendItemEntity) {
                final LegendItemEntity entity = (LegendItemEntity) e;
                final Comparable<?> seriesKey = entity.getSeriesKey();
                final XYPlot plot = (XYPlot) this.chart.getPlot();
                final XYDataset dataset = plot.getDataset();
                final XYItemRenderer renderer = plot.getRenderer();

                if (event.getTrigger().getClickCount() == 2) {
                    for (int i = 0; i < dataset.getSeriesCount(); i++) {
                        if (dataset.getSeriesKey(i).equals(seriesKey)) {
                            final boolean visible = renderer.getItemVisible(i, 0);
                            renderer.setSeriesVisible(i, Boolean.valueOf(!visible));
                            renderer.setSeriesVisibleInLegend(i, true);
                        }
                    }
                }
            }
        }
    }

paradoxoff
Posts: 1634
Joined: Sat Feb 17, 2007 1:51 pm

Re: Clicking on Legend

Post by paradoxoff » Mon Aug 07, 2017 8:04 pm

You have mixed some flags (SeriesVisibleInLegend, SeriesVisible, and ItemVisible). Just use the SeriesVisibleInLegend flag, and nothing else.
If a series is not visible, it will not appear in the legend, even it its SeriesVisibleInLegend flag is set to true.

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

Re: Clicking on Legend

Post by John Matthews » Mon Aug 07, 2017 11:24 pm

Some alternative approaches to restoring visibility are examined here.

benoitx
Posts: 40
Joined: Fri Apr 11, 2003 5:29 pm
Location: London, yes England (where else?)
Contact:

Re: Clicking on Legend

Post by benoitx » Tue Aug 08, 2017 12:33 pm

Thank you both for you very useful comments.

I think that I will use a mixture of the comments and the Stackoverflow suggestion.

Thank you & regards from London.
Benoit

Locked