Dan
Dan

Reputation: 195

Unable to change legend shape and font in polar plot

I am trying to create a sky plot in java using the jfreechart polar plot. Everything is working fine. However i was not able to change the various series legend markers and their size.

Here is an example for my code:

public class Skyplot {
       private JFrame plotFrame = null;

       public static void main (String[] args){
           Skyplot sp = new Skyplot();
           sp.display();
       }

       public Skyplot(){
       }

       public void display(){
           javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    plot(); 
                }
            });
       }

       private void plot(){
           // create and set up the window
           plotFrame = new JFrame("Visualizer");
           plotFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
           //Display the window.
           plotFrame.pack();
           plotFrame.setVisible(true);
           plotFrame.setLocation(500, 500);
           plotFrame.setSize(1200, 900);

           // set up the content pane
           Container C = plotFrame.getContentPane();

           Plotter pl = new Plotter();
           pl.setBorder(BorderFactory.createRaisedBevelBorder());
           pl.setBackground(Color.WHITE);

           C.setLayout(new GridLayout(1, 1));
           C.add(pl);  
       }


       private class Plotter extends JPanel {
           private static final long serialVersionUID = 1L;

           public Plotter(){ 
               XYDataset dataset = getXYDataset();

               final ChartPanel chartPanel = createChartPanel(dataset);
               this.add(chartPanel, BorderLayout.CENTER);
           }

           private ChartPanel createChartPanel(XYDataset dataset) {
               // Create chart
               JFreeChart chart = ChartFactory.createPolarChart("Skyplot", dataset, true, true, false);

               PolarPlot polPlot = (PolarPlot) chart.getPlot();
               polPlot.setRadiusMinorGridlinesVisible(false);
               polPlot.setBackgroundPaint(Color.WHITE);
               polPlot.setRadiusGridlinePaint(Color.DARK_GRAY);
               polPlot.setAngleGridlinePaint(Color.BLACK);

               DefaultPolarItemRenderer renderer = (DefaultPolarItemRenderer) polPlot.getRenderer();
               renderer.setBaseLegendShape(new Rectangle(15,15));
               Font legend_font = new Font("Verdana", Font.PLAIN, 24);
               renderer.setBaseLegendTextFont(legend_font);

               NumberAxis rangeAxis = (NumberAxis) polPlot.getAxis();
               rangeAxis.setTickUnit(new NumberTickUnit(10.0));
               rangeAxis.setMinorTickMarksVisible(false);
               rangeAxis.setRange(0.0, 90.0);
               rangeAxis.setInverted(true);


               return new ChartPanel(chart){
                   @Override
                   public Dimension getPreferredSize() {
                       double H = plotFrame.getHeight()*0.9;
                       double W = plotFrame.getWidth()*0.9;
                       return new Dimension((int)W, (int)H);
                   }
               };
           }

           private XYDataset getXYDataset() {
               XYSeriesCollection dataset = new XYSeriesCollection();

              XYSeries g01= new XYSeries("G01");
              series.add(35, 45);
              dataset.addSeries(g01);

              XYSeries g02= new XYSeries("G02");
              series.add(105, 73);
              dataset.addSeries(g01);

              XYSeries g03= new XYSeries("G03");
              series.add(264, 15);
              dataset.addSeries(g03);

              return dataset;
           }

       }

    }

Any idea why would it not work? Am i doing something wrong with the Renderer? Any help would be appreciated. thank you.

Upvotes: 1

Views: 545

Answers (2)

trashgod
trashgod

Reputation: 205875

The missing piece appears to be telling the parent AbstractRenderer to setShapesVisible().

renderer.setShapesVisible(true);

I want to make all shapes rectangle and the text inside the legend larger.

To coordinate colors and shapes in the chart and legend, use a custom DrawingSupplier, as suggested here. The exact details will depend on your use case, but the basic approach would be to override the DefaultDrawingSupplier methods getNextPaint() and getNextShape() so they return your chosen colors and shapes.

To make the legend text larger, update the chart's LegendTitle, as illustrated below.

LegendTitle title = chart.getLegend();
title.setItemFont(new Font(Font.SERIF, Font.BOLD, 24));

image

As updated:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/** @see https://stackoverflow.com/a/46931762/230513 */
public class Skyplot {

    private JFrame plotFrame = null;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Skyplot()::plot);
    }

    private void plot() {
        plotFrame = new JFrame("Visualizer");
        plotFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        plotFrame.add(new Plotter());
        plotFrame.pack();
        plotFrame.setLocationRelativeTo(null);
        plotFrame.setVisible(true);
    }

    private static final class Plotter extends JPanel {

        public Plotter() {
            super(new GridLayout());
            this.add(createChartPanel(getXYDataset()));
        }

        private ChartPanel createChartPanel(XYDataset dataset) {
            JFreeChart chart = ChartFactory.createPolarChart("Skyplot", dataset, true, true, false);
            LegendTitle title = chart.getLegend();
            title.setItemFont(new Font(Font.SERIF, Font.BOLD, 24));

            PolarPlot polPlot = (PolarPlot) chart.getPlot();
            polPlot.setRadiusMinorGridlinesVisible(false);
            polPlot.setBackgroundPaint(Color.WHITE);
            polPlot.setRadiusGridlinePaint(Color.DARK_GRAY);
            polPlot.setAngleGridlinePaint(Color.BLACK);

            DefaultPolarItemRenderer renderer = (DefaultPolarItemRenderer) polPlot.getRenderer();
            renderer.setShapesVisible(true);

            NumberAxis rangeAxis = (NumberAxis) polPlot.getAxis();
            rangeAxis.setTickUnit(new NumberTickUnit(10.0));
            rangeAxis.setMinorTickMarksVisible(false);
            rangeAxis.setRange(0.0, 90.0);
            rangeAxis.setInverted(true);

            return new ChartPanel(chart) {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(800, 600);
                }
            };
        }

        private XYDataset getXYDataset() {
            XYSeriesCollection dataset = new XYSeriesCollection();

            XYSeries g01 = new XYSeries("G01");
            g01.add(35, 45);
            dataset.addSeries(g01);

            XYSeries g02 = new XYSeries("G02");
            g02.add(105, 73);
            dataset.addSeries(g02);

            XYSeries g03 = new XYSeries("G03");
            g03.add(264, 15);
            dataset.addSeries(g03);

            return dataset;
        }
    }
}

Upvotes: 1

Dan
Dan

Reputation: 195

I have used the advise from above. The method to create the chart looks like this now:

private ChartPanel createChartPanel(XYDataset dataset) {
               // Create chart
               JFreeChart chart = ChartFactory.createPolarChart("Skyplot", dataset, true, true, false);

               PolarPlot polPlot = (PolarPlot) chart.getPlot();
               polPlot.setRadiusMinorGridlinesVisible(false);
               polPlot.setBackgroundPaint(Color.WHITE);
               polPlot.setRadiusGridlinePaint(Color.DARK_GRAY);
               polPlot.setAngleGridlinePaint(Color.BLACK);
               polPlot.setDrawingSupplier(new DrawingSupplier() {
                    @Override
                    public Paint getNextFillPaint() {
                        // TODO Auto-generated method stub
                        return null;
                    }

                    @Override
                    public Paint getNextOutlinePaint() {
                        // TODO Auto-generated method stub
                        return null;
                    }

                    @Override
                    public Stroke getNextOutlineStroke() {
                        // TODO Auto-generated method stub
                        return null;
                    }

                    @Override
                    public Paint getNextPaint() {
                        Random rand = new Random();
                        int r = rand.nextInt(255);
                        int g = rand.nextInt(255);
                        int b = rand.nextInt(255);

                        return new Color(r,g,b);
                    }

                    @Override
                    public Shape getNextShape() {
                        return ShapeUtilities.createDiamond(5f);
                    }


                    @Override
                    public Stroke getNextStroke() {
                        // TODO Auto-generated method stub
                        return null;
                    }

                });

               NumberAxis rangeAxis = (NumberAxis) polPlot.getAxis();
               rangeAxis.setTickUnit(new NumberTickUnit(10.0));
               rangeAxis.setMinorTickMarksVisible(false);
               rangeAxis.setRange(0.0, 90.0);
               rangeAxis.setInverted(true);

               LegendTitle legend = chart.getLegend();
               Font legend_font = new Font("Verdana", Font.BOLD, 18);
               legend.setItemFont(legend_font);

               return new ChartPanel(chart){
                   @Override
                   public Dimension getPreferredSize() {
                       double H = plotFrame.getHeight()*0.9;
                       double W = plotFrame.getWidth()*0.9;
                       return new Dimension((int)W, (int)H);
                   }
               };
           }

The result of using the DrawingSupplier is as follows: resulting skyplot

Upvotes: 1

Related Questions