Search code examples
javajfreechart

JFreeChart: how to set gradient paint for series in spider chart


I have a chart with this presentation:

Current chart

But I require to do this:

Expected chart

How do I set correctly the gradient paint for series?. Here is what I have:

public class SpiderWebChartDemo1 extends ApplicationFrame {

    public SpiderWebChartDemo1(String s) {
        super(s);
        JPanel jpanel = createDemoPanel();
        jpanel.setPreferredSize(new Dimension(500, 270));
        setContentPane(jpanel);
    }

    private static CategoryDataset createDataset() {
        String s = "First";
        String s3 = "Self leadership";
        String s4 = "Organization leadership";
        String s5 = "Team leadership";
        
        DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();
        defaultcategorydataset.addValue(1.0D, s, s3);
        defaultcategorydataset.addValue(4D, s, s4);
        defaultcategorydataset.addValue(3D, s, s5);
        return defaultcategorydataset;
    }

    private static JFreeChart createChart(CategoryDataset categorydataset) {
        Color bckColor1 = Color.decode("#4282CE"); //Light blue
        Color bckColor2 = Color.decode("#9BC1FF"); //Dark blue
        Color axisColor = Color.decode("#DD0010"); //Red
        
        SpiderWebPlot plot = new SpiderWebPlot(categorydataset);
        Paint p = new GradientPaint(0,0,bckColor1,0,0,bckColor2);
        
        plot.setSeriesPaint(p);
        plot.setAxisLinePaint(axisColor);
        
        JFreeChart chart = new JFreeChart("Spider Web Chart Demo 1"
                , TextTitle.DEFAULT_FONT, plot, false);

        LegendTitle legendtitle = new LegendTitle(plot);
        legendtitle.setPosition(RectangleEdge.BOTTOM);
        chart.addSubtitle(legendtitle);
        return chart;
    }

    public static JPanel createDemoPanel() {
        JFreeChart jfreechart = createChart(createDataset());
        return new ChartPanel(jfreechart);
    }

    public static void main(String args[]) {
        SpiderWebChartDemo1 spiderwebchartdemo1 = new SpiderWebChartDemo1("SpiderWebChartDemo1");
        spiderwebchartdemo1.pack();
        RefineryUtilities.centerFrameOnScreen(spiderwebchartdemo1);
        spiderwebchartdemo1.setVisible(true);
    }
}

I've seen gradient paint in bar charts, but not for spider charts. All I'm getting is transparent series.

Thanks.


Solution

  • You are setting the paint correctly however there are 2 things you should realize.

    • Gradient paints in java declare a start and end point. The first color will start at point 1 and transform into color 2 at point 2. If you use it to draw a polygon then the points are not relative to the polygons dimensions. Heres a picture to display, pt1 and pt2 in the picture are where your gradient start and end points are defined.

    enter image description here

    • In an ideal world every setting is editable in a library but many times this just isnt the case. We can overcome that by overwriting methods in a subclass. You will need to override the SpiderWebPlot class and implement some of the painting methods. Heres a quick class I wrote up that does just that.

    Take a look at the very end where it actually draws the polygon. I took this directly from the SpiderWebPlot source and altered the very end. To use this in your program call it like this GradientSpiderWebPlot plot = new GradientSpiderWebPlot(categorydataset, Color.decode("#4282CE"), Color.decode("#9BC1FF"), .8f);

    Here are the results

    enter image description here

    public class GradientSpiderWebPlot extends SpiderWebPlot {
    
        private Color startColor, endColor;
        private float alpha;
    
        public GradientSpiderWebPlot(CategoryDataset data, Color startColor, Color endColor, float alpha) {
            // TODO Auto-generated constructor stub
            super(data);
            this.startColor = startColor;
            this.endColor = endColor;
            this.alpha = alpha;
        }
    
        @Override
        protected void drawRadarPoly(Graphics2D g2,
                                     Rectangle2D plotArea,
                                     Point2D centre,
                                     PlotRenderingInfo info,
                                     int series, int catCount,
                                     double headH, double headW) {
    
            Polygon polygon = new Polygon();
    
            EntityCollection entities = null;
            if (info != null) {
                entities = info.getOwner().getEntityCollection();
            }
    
            // plot the data...
            for (int cat = 0; cat < catCount; cat++) {
    
                Number dataValue = getPlotValue(series, cat);
    
                if (dataValue != null) {
                    double value = dataValue.doubleValue();
    
                    if (value >= 0) { // draw the polygon series...
    
                        // Finds our starting angle from the centre for this axis
    
                        double angle = getStartAngle()
                            + (getDirection().getFactor() * cat * 360 / catCount);
    
                        // The following angle calc will ensure there isn't a top
                        // vertical axis - this may be useful if you don't want any
                        // given criteria to 'appear' move important than the
                        // others..
                        //  + (getDirection().getFactor()
                        //        * (cat + 0.5) * 360 / catCount);
    
                        // find the point at the appropriate distance end point
                        // along the axis/angle identified above and add it to the
                        // polygon
    
                        Point2D point = getWebPoint(plotArea, angle,
                                value / this.getMaxValue());
                        polygon.addPoint((int) point.getX(), (int) point.getY());
    
                        // put an elipse at the point being plotted..
    
                        Paint paint = getSeriesPaint(series);
                        Paint outlinePaint = getSeriesOutlinePaint(series);
                        Stroke outlineStroke = getSeriesOutlineStroke(series);
    
                        Ellipse2D head = new Ellipse2D.Double(point.getX()
                                - headW / 2, point.getY() - headH / 2, headW,
                                headH);
                        g2.setPaint(paint);
                        g2.fill(head);
                        g2.setStroke(outlineStroke);
                        g2.setPaint(outlinePaint);
                        g2.draw(head);
    
                        if (entities != null) {
                            int row = 0; int col = 0;
                            if (this.getDataExtractOrder() == TableOrder.BY_ROW) {
                                row = series;
                                col = cat;
                            }
                            else {
                                row = cat;
                                col = series;
                            }
                            String tip = null;
                            if (this.getToolTipGenerator() != null) {
                                tip = this.getToolTipGenerator().generateToolTip(
                                        this.getDataset(), row, col);
                            }
    
                            String url = null;
                            if (this.getURLGenerator() != null) {
                                url = this.getURLGenerator().generateURL(this.getDataset(),
                                       row, col);
                            }
    
                            Shape area = new Rectangle(
                                    (int) (point.getX() - headW),
                                    (int) (point.getY() - headH),
                                    (int) (headW * 2), (int) (headH * 2));
                            CategoryItemEntity entity = new CategoryItemEntity(
                                    area, tip, url, this.getDataset(),
                                    this.getDataset().getRowKey(row),
                                    this.getDataset().getColumnKey(col));
                            entities.add(entity);
                        }
    
                    }
                }
            }
            // Plot the polygon
    
            // Lastly, fill the web polygon if this is required
    
            Rectangle2D rec = polygon.getBounds2D();
    
            //Paint paint = getSeriesPaint(series);
            // create linear vertical gradient based upon the bounds of the polygon.
            Paint paint = new GradientPaint(new Point2D.Double(rec.getCenterX(),rec.getMinY()), startColor,
                    new Point2D.Double(rec.getCenterX(),rec.getMaxY()), endColor);
    
            g2.setPaint(paint);
            g2.setStroke(getSeriesOutlineStroke(series));
            g2.draw(polygon);
    
    
            if (this.isWebFilled()) {
                // made this the variable alpha instead of the fixed .1f
                g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                        alpha));
                g2.fill(polygon);
                g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                        getForegroundAlpha()));
            }
        }
    }