13

I have thousands of points to Plot on a JFreeChart scatter plot. The problem right now is that my program is plotting points with "squares", but I need some help on how to change the Shape of points from "squares" to "dots/circles". Any help would be appreciated.

//*I am using ShapeUtilities,but its not changing the shape of point to "DaigonalCross" when I am Using for XYItemRenderer/XYDotRenderer--Any corrections please if anythng wrong in the code ..*///

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Shape;
import java.util.*;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYDotRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.util.ShapeUtilities;

public class SPlotfinal extends ApplicationFrame {

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

    public static JPanel createDemoPanel() {

        JFreeChart jfreechart = ChartFactory.createScatterPlot("Scatter Plot Demo",
            "X", "Y", samplexydataset2(), PlotOrientation.VERTICAL, true, true, false);
        Shape cross = ShapeUtilities.createDiagonalCross(3, 1);

        XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
        XYItemRenderer renderer = xyPlot.getRenderer();
        renderer.setBaseShape(cross);
        renderer.setBasePaint(Color.red);
        //changing the Renderer to XYDotRenderer
        //xyPlot.setRenderer(new XYDotRenderer());
        XYDotRenderer xydotrenderer = new XYDotRenderer();
        xyPlot.setRenderer(xydotrenderer);
        xydotrenderer.setSeriesShape(0, cross);

        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);

        return new ChartPanel(jfreechart);
    }

    private static XYDataset samplexydataset2() {
        int cols = 20;
        int rows = 20;
        double[][] values = new double[cols][rows];

        XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
        XYSeries series = new XYSeries("Random");
        Random rand = new Random();
        for (int i = 0; i < values.length; i++) {
            for (int j = 0; j < values[i].length; j++) {
                double x = Math.round(rand.nextDouble() * 500);
                double y = Math.round(rand.nextDouble() * 500);

                series.add(x, y);
            }
        }
        xySeriesCollection.addSeries(series);
        return xySeriesCollection;
    }

    public static void main(String args[]) {
        SPlotfinal scatterplotdemo4 = new SPlotfinal("Scatter Plot Demo 4");
        scatterplotdemo4.pack();
        RefineryUtilities.centerFrameOnScreen(scatterplotdemo4);
        scatterplotdemo4.setVisible(true);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Sam
  • 603
  • 3
  • 7
  • 17

2 Answers2

20

A ScatterRenderer inherits getItemShape() from AbstractRenderer. You can override getItemShape() to supply your own shapes.

Addendum: One advantage to this approach is that you can specify a Shape for each item in each series.

Addendum: To use ShapeUtilities.createDiagonalCross(), do something like this:

Shape cross = ShapeUtilities.createDiagonalCross(3, 1);
plot = (XYPlot) chart.getPlot();
renderer = plot.getRenderer();
renderer.setSeriesShape(0, cross);

Addendum: Just switch to setSeriesShape(). Also, skip the XYDotRenderer and Math.round().

Scatter Plot Demo

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Shape;
import java.util.*;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.util.ShapeUtilities;

public class SPlotfinal extends ApplicationFrame {

    public SPlotfinal(String s) {
        super(s);
        JPanel jpanel = createDemoPanel();
        jpanel.setPreferredSize(new Dimension(640, 480));
        add(jpanel);
    }

    public static JPanel createDemoPanel() {
        JFreeChart jfreechart = ChartFactory.createScatterPlot(
            "Scatter Plot Demo", "X", "Y", samplexydataset2(),
            PlotOrientation.VERTICAL, true, true, false);
        Shape cross = ShapeUtilities.createDiagonalCross(3, 1);
        XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);
        XYItemRenderer renderer = xyPlot.getRenderer();
        renderer.setSeriesShape(0, cross);
        renderer.setSeriesPaint(0, Color.red);
        return new ChartPanel(jfreechart);
    }

    private static XYDataset samplexydataset2() {
        int cols = 20;
        int rows = 20;
        double[][] values = new double[cols][rows];
        XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
        XYSeries series = new XYSeries("Random");
        Random rand = new Random();
        for (int i = 0; i < values.length; i++) {
            for (int j = 0; j < values[i].length; j++) {
                double x = rand.nextGaussian();
                double y = rand.nextGaussian();
                series.add(x, y);
            }
        }
        xySeriesCollection.addSeries(series);
        return xySeriesCollection;
    }

    public static void main(String args[]) {
        SPlotfinal scatterplotdemo4 = new SPlotfinal("Scatter Plot Demo 4");
        scatterplotdemo4.pack();
        RefineryUtilities.centerFrameOnScreen(scatterplotdemo4);
        scatterplotdemo4.setVisible(true);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    [`DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE`](http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/plot/DefaultDrawingSupplier.html#DEFAULT_SHAPE_SEQUENCE) is handy, too. – trashgod Jul 14 '11 at 04:46
  • Can You Please post the Code of above "ScatterPlotDemo" ,That is what I am exactly Looking for....Thanks – Sam Jul 14 '11 at 10:23
  • Too long; I've adapted your example, above. – trashgod Jul 14 '11 at 16:26
  • Great....Thanks Very Much for Editing the code;)..If Possible can u please post the Code of Previous Diagram-"ScatterPlotDemo" which was having all the shapes..Thanks – Sam Jul 14 '11 at 19:01
  • The extra shapes are supplied automatically by the `DefaultDrawingSupplier`, mentioned above, each time you add another series to your `XYSeriesCollection`. Please consider accepting this answer by clicking on the empty check mark on the left. – trashgod Jul 14 '11 at 19:05
  • @trashgod I am using Shape cross = ShapeUtilities.createRegularCross(2, 1); plot.getRenderer().setSeriesShape(0, cross); for a LineChart. Could you please let me know how can I draw a circle and also how do I change the color of the shape only instead of the line. I had asked this question: http://stackoverflow.com/questions/14952712/plotting-a-hysteresis-loop-with-jfreechart/14962160#14962160 – Gaurav K Feb 19 '13 at 16:57
  • See also this [example](http://stackoverflow.com/a/20359200/230513) that overrides `getItemShape()`. – trashgod Dec 03 '13 at 18:48
7

You can get the plot (for this example its a XYPlot) and then the renderer and change the base shape like this:

// 5x5 red pixel circle
Shape shape  = new Ellipse2D.Double(0,0,5,5);
XYPlot xyPlot = (XYPlot) jFreeCHart.getPlot();
XYItemRenderer renderer = xyPlot.getRenderer();
renderer.setBaseShape(shape);
renderer.setBasePaint(Color.red);

// set only shape of series with index i
renderer.setSeriesShape(i, shape);

You can change much more things, like outline paint/stroke

timaschew
  • 16,254
  • 6
  • 61
  • 78
  • Sadly, this won't work, as [`setBaseShape()`](http://www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/renderer/xy/XYItemRenderer.html#line.691) and [`setSeriesShape()`](http://www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/renderer/xy/XYItemRenderer.html#line.670) appear unimplemented. – trashgod Jul 13 '11 at 15:38
  • 1
    Fortunately, there is usable [`setSeriesShape()`](http://www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/renderer/AbstractRenderer.html#line.1631) in the base class, `AbstractRenderer`. – trashgod Jul 13 '11 at 15:51
  • I tried with ur code it worked...I have other question.I have a method createDiagonalCross(float l, float t) in "Class ShapeUtilities" which Creates a diagonal cross shape for points,how can i use this method with the above code..need help regarding this..Thanks – Sam Jul 13 '11 at 16:28