3

I have a dynamic Area Chart and I want to add a green point on the last point where my chart is displayed(the recent value on my chart).For example with displaying the line border i want a big green point to be displayed on my area chart? I'm working with an example shown here .

How to do this? There's my code:

 public class essaijfree2 extends ApplicationFrame {

private static final String TITLE = "Dynamic Series";
private static final String START = "Start";
private static final String STOP = "Stop";
private static final float MINMAX = 100;
private static final int COUNT = 2 * 60;
private static final int FAST = 100;
private static final int SLOW = FAST * 5;
private static final Random random = new Random();
private Timer timer;

public essaijfree2(final String title) {
    super(title);
    final DynamicTimeSeriesCollection dataset =
        new DynamicTimeSeriesCollection(1, COUNT, new Second());
    dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2011));
    dataset.addSeries(gaussianData(), 0, "Gaussian data");
    JFreeChart chart = createChart(dataset);
    XYPlot xyPlot = (XYPlot) chart.getPlot();
    XYDifferenceRenderer r = new XYDifferenceRenderer(Color.green,Color.red, true);
    xyPlot.setRenderer(r);



    final JComboBox combo = new JComboBox();
    combo.addItem("Fast");
    combo.addItem("Slow");
    combo.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            if ("Fast".equals(combo.getSelectedItem())) {
                timer.setDelay(FAST);
            } else {
                timer.setDelay(SLOW);
            }
        }
    });

    this.add(new ChartPanel(chart), BorderLayout.CENTER);
    JPanel btnPanel = new JPanel(new FlowLayout());

    btnPanel.add(combo);
    this.add(btnPanel, BorderLayout.SOUTH);

    timer = new Timer(FAST, new ActionListener() {

        float[] newData = new float[1];

        @Override
        public void actionPerformed(ActionEvent e) {
            newData[0] = randomValue();
            dataset.advanceTime();
            dataset.appendData(newData);
        }
    });
}

private float randomValue() {

    return (float) (random.nextGaussian() * MINMAX / 3);
}

private float[] gaussianData() {
    float[] a = new float[COUNT];
    for (int i = 0; i < a.length; i++) {
        a[i] = randomValue();
    }
    return a;
}

private JFreeChart createChart(final XYDataset dataset) {
    final JFreeChart result = ChartFactory.createXYAreaChart(
        TITLE, "hh:mm:ss", "milliVolts", dataset,PlotOrientation.VERTICAL, true, true, false);
    final XYPlot plot = result.getXYPlot();
    ValueAxis domain = plot.getDomainAxis();
    domain.setAutoRange(true);

    ValueAxis range = plot.getRangeAxis();
    range.setRange(-MINMAX, MINMAX);
    return result;
}

public void start() {
    timer.start();
}

public static void main(final String[] args) {
    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            essaijfree2 demo = new essaijfree2(TITLE);
            demo.pack();
            RefineryUtilities.centerFrameOnScreen(demo);
            demo.setVisible(true);
            demo.start();
        }
    });
}
Community
  • 1
  • 1
hamza-don
  • 455
  • 5
  • 26

2 Answers2

4

I'd look at an XYShapeAnnotation positioned at the coordinates of the last added datum. Some examples are seen here. You can use a RadialGradientPaint with varying alpha to get the halo effect. I've never tried doing it dynamically, but XYPlot includes the methods addAnnotation() and removeAnnotation(); both notify all registered listeners.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    XYShapeAnnotation is a good option, but since this green point is always on the last data point plotted, to me it would make sense for it to be drawn by the renderer (obviously you'd need to subclass or copy-and-modify the existing renderer, but it should not be a difficult change to make locally). – David Gilbert Dec 18 '13 at 17:50
1

I recommend to create your own XYAnnotation that a) doesn´t used predefined x and y values but instead picks them from the dataset and that b) uses a shape whose bounds are defined in Java2D space so that the shape size remains constant when you zoom in. Here is an example:

Item Annotation Demo

public class ItemAnnotationDemo {

    public static void main(String[] args) {
        int count = 20;
        double[][] data = new double[2][count];
        for(int i = 0; i < count; i++){
            data[0][i] = i;
            data[1][i] = i;
        }
        DefaultXYDataset dataset = new DefaultXYDataset();
        dataset.addSeries("Values", data);
        NumberAxis xAxis = new NumberAxis("x axis");
        NumberAxis yAxis = new NumberAxis("y axis");
        XYItemRenderer renderer = new XYLineAndShapeRenderer(true, true);
        renderer.addAnnotation(new XYItemAnnotation(
            new Rectangle2D.Double(-10, -8, 20, 16),
            new Color(128,128,128,128),
            new BasicStroke(3.0f),
            Color.RED,0,Integer.MAX_VALUE));
        XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
        JFreeChart chart = new JFreeChart(plot);
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new ChartPanel(chart));
        frame.pack();
        frame.setVisible(true);

    }
}
class XYItemAnnotation extends AbstractXYAnnotation{
    private Shape shape;
    private Paint outline;
    private Paint fill;
    private Stroke stroke;
    private int si;
    private int ii;
    public XYItemAnnotation(Shape shape, Paint fillPaint, Stroke outlineStroke, Paint outlinePaint, int seriesIndex, int itemIndex){
        super();
        this.shape = shape;
        this.fill = fillPaint;
        this.stroke = outlineStroke;
        this.outline = outlinePaint;
        this.si = seriesIndex;
        this.ii = itemIndex;
    }
    public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int datasetIndex, PlotRenderingInfo info){
        XYDataset dataset = plot.getDataset(datasetIndex);
        if(dataset == null) return;
        if(si > dataset.getSeriesCount() - 1 ) return;
        int item = Math.max(0, ii);
        item = Math.min(item, dataset.getItemCount(si) - 1);
        double dx = dataset.getXValue(si, item);
        double dy = dataset.getYValue(si, item);
        if(Double.isNaN(dx) || Double.isNaN(dy)) return;
        if(!domainAxis.getRange().contains(dx) || !rangeAxis.getRange().contains(dy)) return;
        PlotOrientation orientation = plot.getOrientation();
        RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
                plot.getDomainAxisLocation(), orientation);
        RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
                plot.getRangeAxisLocation(), orientation);

        double jx = domainAxis.valueToJava2D(dx, dataArea, domainEdge);
        double jy = rangeAxis.valueToJava2D(dy, dataArea, rangeEdge);
        if (orientation == PlotOrientation.HORIZONTAL) {
            double temp = jx;
            jx = jy;
            jy = temp;
        }
        Shape trans = ShapeUtilities.createTranslatedShape(shape, jx, jy);
        g2.setPaint(fill);
        g2.fill(trans);
        g2.setPaint(outline);
        g2.setStroke(stroke);
        g2.draw(trans);

    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Soltub
  • 101
  • 2