Reputation: 195
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
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));
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
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