Refresh legend after changing series color?

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
esword
Posts: 10
Joined: Tue Apr 05, 2005 7:53 pm
Location: Virginia

Refresh legend after changing series color?

Post by esword » Thu Mar 16, 2006 6:44 pm

I wrote a cewolf ChartPostProcessor to modify the color of the series in a chart rather than using the default ones. Changing the actual series colors was easy, but I don't see a quick way to get the legend to refresh the color boxes next to the LegendItems with the new colors. The LegendItems themselves (retrieved via the plot.getLegendItems()) are immutable, and I can't see anyway to refresh the LegendTitle either. Am I missing something easy, or do I have to rebuild the whole legend by iterating over the existing one, creating new items with modified colors, adding those to a new LegendItemCollection, and then calling plot.setFixedLegendItems(newColl)?

adTHANKSvance

Eric

Jyothy
Posts: 17
Joined: Fri Mar 24, 2006 6:46 am

Post by Jyothy » Wed Mar 29, 2006 5:44 am

Can you please post the code to change the default series colors using ChartPostProcessor??

Thanks in advance

Jyothy

esword
Posts: 10
Joined: Tue Apr 05, 2005 7:53 pm
Location: Virginia

Post by esword » Wed Mar 29, 2006 2:54 pm

Here is the class I wrote. It makes the assumption that the plot is an XYPlot of some form, but that can be worked around if necessary. It also invokes another utility class for checking if a plot is a combined plot and getting all subplots. You can either ignore that part, write your own, or get that class from the set of chart classes I wrote for the meta-jb project: http://sourceforge.net/project/showfile ... p_id=67888

Code: Select all


    /**
     * Allows setting of colors based on series name.
     */
    public static class ColorSetterRenderer implements ChartPostProcessor
    {
        private Map<Comparable, Paint> seriesColorMap = new HashMap<Comparable, Paint>();

        public void processChart(Object obj, Map params)
        {
            try
            {
                JFreeChart chart = (JFreeChart)obj;
                changeSeriesColors(chart);
                changeLegendColors(chart);
            }
            catch (Exception e)
            {
                log.error("Error setting colors ", e);
            }
        }

        /**
         * Iterate over all the plots in the chart and all the datasets in those plots and
         * then all the series in the datasets, changing the color of series that match entries
         * in our color map.
         * @param chart
         */
        private void changeSeriesColors(JFreeChart chart) {
            List<Plot> plots = getPlots(chart);
            LegendTitle lt = chart.getLegend();

            for (Plot plot : plots)
            {
                DrawingSupplier rootSupplier = plot.getDrawingSupplier();
                XYPlot xyPlot = (XYPlot)plot;

                for (int i = 0; i < xyPlot.getDatasetCount(); i++)
                {
                    XYDataset curDataset = xyPlot.getDataset(i);
                    XYItemRenderer curRenderer = xyPlot.getRendererForDataset(curDataset);
                    DrawingSupplier curSupplier = rootSupplier;
                    if (curRenderer instanceof AbstractXYItemRenderer)
                        curSupplier = ((AbstractXYItemRenderer)curRenderer).getDrawingSupplier();

                    //for each series in each dataset, see if there is an entry for the color
                    //in the color map.  If not, make sure the currently assigned color doesn't
                    //conflict with one in the map.
                    for (int curSeries = 0; curSeries < curDataset.getSeriesCount(); curSeries++)
                    {
                        Comparable key = curDataset.getSeriesKey(curSeries);
                        Paint curPaint = curRenderer.getSeriesPaint(curSeries);
                        if (seriesColorMap.containsKey(key))
                        {
                            Paint assignedPaint = seriesColorMap.get(key);
                            if (!assignedPaint.equals(curPaint));
                                curRenderer.setSeriesPaint(curSeries, assignedPaint);
                        }
                        else if (seriesColorMap.containsValue(curPaint))
                        {
                            //change the color so we don't conflict with a series that is
                            //in the map
                            while (seriesColorMap.containsValue(curPaint))
                                curPaint = curSupplier.getNextPaint();

                            curRenderer.setSeriesPaint(curSeries, curPaint);
                        }
                    }
                }
            }
        }

        /**
         * LegendItems are immutable, as is the Legend contents.  So must go through
         * all Legend items and create new ones when the color has changed.  Then add
         * them all to a new legend and set that.
         * @param chart
         */
        private void changeLegendColors(JFreeChart chart) {
            LegendItemCollection newLegend = new LegendItemCollection();
            XYPlot mainPlot = (XYPlot)chart.getPlot();
            LegendItemCollection legend = mainPlot.getLegendItems();
            for (Iterator iter = legend.iterator(); iter.hasNext();)
            {
                LegendItem item = (LegendItem) iter.next();
                String label = item.getLabel();
                Paint assignedPaint = seriesColorMap.get(label);
                //if there is a new paint for the series that this item represents,
                //create a new item for it
                if (assignedPaint != null)
                    item = createLabel(item, assignedPaint);

                //add either existing or new one to the new legend
                newLegend.add(item);
            }
            //now set the new items as fixed so it won't regenerate it
            if (newLegend.getItemCount() > 0)
                mainPlot.setFixedLegendItems(newLegend);
        }

        private LegendItem createLabel(LegendItem item, Paint assignedPaint) {
            LegendItem retVal = new LegendItem(item.getLabel(), item.getDescription(),
                    item.getToolTipText(), item.getURLText(), item.isShapeVisible(), item.getShape(),
                    item.isShapeFilled(), assignedPaint, item.isShapeOutlineVisible(),
                    item.getOutlinePaint(), item.getOutlineStroke(), item.isLineVisible(),
                    item.getLine(), item.getLineStroke(), item.getLinePaint());
            return retVal;
        }

        public void setColor(Comparable seriesName, Paint color)
        {
            seriesColorMap.put(seriesName, color);
        }

        public Map<Comparable, Paint> getSeriesColorMap() {
            return seriesColorMap;
        }

        public void setSeriesColorMap(Map<Comparable, Paint> seriesColorMap) {
            this.seriesColorMap = seriesColorMap;
        }
    }

    private static List<Plot> getPlots(JFreeChart chart) {
        List<Plot> retVal = null;

        XYPlot plot = (XYPlot) chart.getPlot();
        if (ChartUtils.isCombinedPlot(plot))
        {
            retVal = ChartUtils.getSubPlots(plot);
        }
        else
        {
            retVal = new ArrayList<Plot>();
            retVal.add(plot);
        }

        return retVal;
    }

Locked