moving the whole chart to right/left, up/down

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
hotwingz
Posts: 10
Joined: Fri Apr 01, 2005 11:06 pm

moving the whole chart to right/left, up/down

Post by hotwingz » Wed Jun 14, 2006 8:04 pm

Hello,
I'm using XYSeriesCollection to graph a number of peaks. Each peak is composed of one XYSeries. The XYDataset is used to construct a single chart which is then used to construct a ChartPanel. All standard so far.

What I'd like to do is the follows:
When the right arrow is pressed, I'd like the whole chart to move towards the right. The ValueAxis has to remain the same, but the chart has to move.

I tried iterating through the XYSeriesCollection and the XYSeries adding a number to the actual X values and then repainting the ChartPanel. But, some peaks(XYSeries) move while others stay where they are. I'd expected them all to move lockstep.

Any ideas would be appreciated

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Thu Jun 15, 2006 10:41 am

You could write a dataset class that 'wraps' any XYDataset and applies a translation to all the x-values returned by that dataset. Saves having to update all the x-values...
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

hotwingz
Posts: 10
Joined: Fri Apr 01, 2005 11:06 pm

Post by hotwingz » Thu Jun 15, 2006 10:07 pm

Thanks,David.

But, errrrr, I looked at a couple of examples in the forum but those had to do with translating from Java2D to axis coordinates. Could give me a further pointer?

Much appreciated.

hotwingz

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Mon Jun 19, 2006 5:02 pm

This is an example of what I had in mind:

Code: Select all

/* -------------------
 * TranslateDemo1.java
 * -------------------
 * (C) Copyright 2006, by Object Refinery Limited.
 *
 */


import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.Range;
import org.jfree.data.general.DatasetChangeEvent;
import org.jfree.data.general.DatasetChangeListener;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.time.Minute;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.AbstractXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.RefineryUtilities;

/**
 * A wrapper dataset that provides a translation of the underlying dataset.
 */
public class TranslateDemo extends ApplicationFrame {

    private static class DemoPanel extends JPanel 
                                   implements ChangeListener {
    
        private TimeSeries series;
        
        private ChartPanel chartPanel;
        
        private JFreeChart chart;
        
        private JSlider slider;
        
        private TranslatingXYDataset dataset;

        static class TranslatingXYDataset extends AbstractXYDataset 
                implements XYDataset, DatasetChangeListener {
            private XYDataset underlying;
            private double translate;
            public TranslatingXYDataset(XYDataset underlying) {
                this.underlying = underlying;
                this.underlying.addChangeListener(this);
                this.translate = 0.0;
            }
            public double getTranslate() {
                return this.translate;
            }
            public void setTranslate(double t) {
                this.translate = t;
                this.fireDatasetChanged();
            }
            public int getItemCount(int series) {
                return this.underlying.getItemCount(series);
            }
            public double getXValue(int series, int item) {
                return this.underlying.getXValue(series, item) + translate;
            }
            public Number getX(int series, int item) {
                return new Double(getXValue(series, item));
            }
            public Number getY(int series, int item) {
                return new Double(getYValue(series, item));
            }
            public double getYValue(int series, int item) {
                return this.underlying.getYValue(series, item);
            }
            public int getSeriesCount() {
                return this.underlying.getSeriesCount();
            }
            public Comparable getSeriesKey(int series) {
                return underlying.getSeriesKey(series);
            }
            public void datasetChanged(DatasetChangeEvent event) {
                // underlying dataset has changed, so notify our listeners
                this.fireDatasetChanged();
            }
        }
        
        /**
         * Creates a new demo panel.
         */
        public DemoPanel() {
            super(new BorderLayout());
            this.chart = createChart();
            this.chartPanel = new ChartPanel(this.chart);
            this.chartPanel.setPreferredSize(new java.awt.Dimension(600, 270));
            this.chartPanel.setDomainZoomable(true);
            this.chartPanel.setRangeZoomable(true);
            Border border = BorderFactory.createCompoundBorder(
                BorderFactory.createEmptyBorder(4, 4, 4, 4),
                BorderFactory.createEtchedBorder()
            );
            this.chartPanel.setBorder(border);
            add(this.chartPanel);
            
            JPanel dashboard = new JPanel(new BorderLayout());
            dashboard.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));   
            // make the slider units "minutes"
            this.slider = new JSlider(-200, 200, 0);
            slider.setPaintLabels(true);
            slider.setMajorTickSpacing(50);
            slider.setPaintTicks(true);
            this.slider.addChangeListener(this);
            dashboard.add(this.slider);
            add(dashboard, BorderLayout.SOUTH);
        }
        
        /**
         * Creates the demo chart.
         * 
         * @return The chart.
         */
        private JFreeChart createChart() {

            XYDataset dataset1 = createDataset(
                "Random 1", 100.0, new Minute(), 200
            );
            
            JFreeChart chart1 = ChartFactory.createTimeSeriesChart(
                "Translate Demo 1", 
                "Time of Day", 
                "Value",
                dataset1, 
                true, 
                true, 
                false
            );

            chart1.setBackgroundPaint(Color.white);
            XYPlot plot = chart1.getXYPlot();
            plot.setOrientation(PlotOrientation.VERTICAL);
            plot.setBackgroundPaint(Color.lightGray);
            plot.setDomainGridlinePaint(Color.white);
            plot.setRangeGridlinePaint(Color.white);
            plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
            
            plot.setDomainCrosshairVisible(true);
            plot.setDomainCrosshairLockedOnData(false);
            plot.setRangeCrosshairVisible(false);
            XYItemRenderer renderer = plot.getRenderer();
            renderer.setPaint(Color.black);
            // fix the range
            DateAxis axis = (DateAxis) plot.getDomainAxis();
            Range range = DatasetUtilities.findDomainBounds(dataset);
            axis.setRange(range);
            return chart1;
        }
        
        
        /**
         * Creates a sample dataset.
         * 
         * @param name  the dataset name.
         * @param base  the starting value.
         * @param start  the starting period.
         * @param count  the number of values to generate.
         *
         * @return The dataset.
         */
        private XYDataset createDataset(String name, double base, 
                                        RegularTimePeriod start, int count) {

            this.series = new TimeSeries(name, start.getClass());
            RegularTimePeriod period = start;
            double value = base;
            for (int i = 0; i < count; i++) {
                this.series.add(period, value);    
                period = period.next();
                value = value * (1 + (Math.random() - 0.495) / 10.0);
            }

            TimeSeriesCollection tsc = new TimeSeriesCollection();
            tsc.addSeries(this.series);
            this.dataset = new TranslatingXYDataset(tsc);
            return dataset;

        }
        
        /**
         * Handles a state change event.
         * 
         * @param event  the event.
         */
        public void stateChanged(ChangeEvent event) {
            int value = this.slider.getValue();
            // value is in minutes
            this.dataset.setTranslate(value * 60 * 1000.0);
        }

    }
    
    /**
     * A demonstration application showing how to control a crosshair using an
     * external UI component.
     *
     * @param title  the frame title.
     */
    public TranslateDemo(String title) {
        super(title);
        setContentPane(new DemoPanel());
    }

    /**
     * Creates a panel for the demo (used by SuperDemo.java).
     * 
     * @return A panel.
     */
    public static JPanel createDemoPanel() {
        return new DemoPanel();
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {

        TranslateDemo demo = new TranslateDemo("Translate Demo 1");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }
    
}
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Locked