JfreeChart: Scroll XYBarChart Horizontally - (chart translation and navigation)
Asked Answered
A

3

3

I am trying to scroll my XYBarChart horizontally, I am following one of the JfreeChart's Demo "TranslateDemo1.java" in which the source code you can find here:

http://code.google.com/p/cori-chenxx/source/browse/aliper/trunk/aliper-core/src/test/java/com/alibaba/aliper/TranslateDemo1.java?spec=svn148&r=148

The source code works fine for a "TimeSeriesChart".

However I tried with "XYBarChart" and WHEN I SLIDE THE BAR the behavior is not the same.

Just to be clear I replaced the line #157 with the following source code:

JFreeChart chart1= ChartFactory.createXYBarChart(
                "Title", 
                null, 
                true, 
                "Ylabel", 
                xyDatasetTranslating, 
                PlotOrientation.VERTICAL, 
                true, 
                true, 
                false);

Does anyone know why the application is behaving in this way? and how I could possibly fix it.

Thanks,

Actinopod answered 12/7, 2010 at 20:6 Comment(0)
A
9

Here is a source code that implement a simple solution.

TranslateDemo screenshot

import java.awt.BorderLayout;
import java.util.Date;

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.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.time.DateRange;
import org.jfree.data.time.Day;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

public class DomainTranslateDemo extends ApplicationFrame {

    private static class DemoPanel extends JPanel implements ChangeListener {

        private static int SLIDER_INITIAL_VALUE = 50;
        private JSlider slider;
        private DateAxis domainAxis;
        private int lastValue = SLIDER_INITIAL_VALUE;

        // one month (milliseconds, seconds, minutes, hours, days)
        private int delta = 1000 * 60 * 60 * 24 * 30;

        public DemoPanel() {
            super(new BorderLayout());
            JFreeChart chart = createChart();
            ChartPanel chartPanel = new ChartPanel(chart);
            chartPanel.setPreferredSize(new java.awt.Dimension(600, 270));
            chartPanel.setDomainZoomable(true);
            chartPanel.setRangeZoomable(true);
            Border border = BorderFactory.createCompoundBorder(
                BorderFactory.createEmptyBorder(4, 4, 4, 4),
                BorderFactory.createEtchedBorder()
            );
            chartPanel.setBorder(border);
            add(chartPanel);

            JPanel dashboard = new JPanel(new BorderLayout());
            dashboard.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));   

            this.slider = new JSlider(0, 100, SLIDER_INITIAL_VALUE);
            this.slider.addChangeListener(this);
            dashboard.add(this.slider);
            add(dashboard, BorderLayout.SOUTH);
        }

        private JFreeChart createChart() {

            TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();
            TimeSeries series = createSerie(500,20);
            timeSeriesCollection.addSeries(series );

            this.domainAxis = new DateAxis("Time");
            NumberAxis rangeAxis = new NumberAxis("");
            XYBarRenderer renderer = new XYBarRenderer();
            renderer.setShadowVisible(false);
            XYPlot plot = new XYPlot(timeSeriesCollection, domainAxis, rangeAxis, renderer);

            JFreeChart chart = new JFreeChart(
                    "Title", 
                    JFreeChart.DEFAULT_TITLE_FONT,
                    plot, 
                    true);
            // performance
            chart.setAntiAlias(false);
            return chart;
        }

        private TimeSeries createSerie(int domainCount,int rangeCount) {
            TimeSeries timeSeries =  new TimeSeries("timeSeries1");
            Day d = new Day(new Date());
            RegularTimePeriod regularTimePeriod = d.next();
            for (int index = 0; index < domainCount; index++) {
                if (index % 2 == 0) {
                    double value = (Math.random() * rangeCount);
                    timeSeries.add(regularTimePeriod,value);
                }
                regularTimePeriod = regularTimePeriod.next();
            }
            return timeSeries;
        }

        @Override
        public void stateChanged(ChangeEvent event) {
            int value = this.slider.getValue();
            long minimum = domainAxis.getMinimumDate().getTime();
            long maximum = domainAxis.getMaximumDate().getTime();
            if (value<lastValue) { // left
                minimum = minimum - delta;
                maximum = maximum - delta;
            } else { // right
                minimum = minimum + delta;
                maximum = maximum + delta;
            }
            DateRange range = new DateRange(minimum,maximum);
            domainAxis.setRange(range);
            lastValue = value;
        }

    }

    public DomainTranslateDemo(String title) {
        super(title);
        setContentPane(new DemoPanel());
    }

    public static JPanel createDemoPanel() {
        return new DemoPanel();
    }

    public static void main(String[] args) {
        DomainTranslateDemo demo = new DomainTranslateDemo("Translate Demo");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

} 
Actinopod answered 16/7, 2010 at 22:55 Comment(2)
hi, your code apply in barchart using Jfreechart (Eclipse RCP),,,any idea & suggestion...quickly inform...thanks...Nunes
@BharatZala It should, it has been 7 years that I don't use this API. Let me know if you were able to use this code.Actinopod
S
1

TranslatingXYDataset presently implements XYDataset; instead, you'll need to implement IntervalXYDataset, as required by JFreeChart.createXYBarChart.

Styria answered 13/7, 2010 at 0:33 Comment(2)
Yep, you are right. BUT still not working :(. When I implement the IntervalXYDataset instead of XYDataset I have to code some other methods such as: @Override public double getStartXValue(int series, int item) { return underlying.getStartXValue(series, item); } @Override public double getEndXValue(int series, int item) { return underlying.getEndXValue(series, item); } I am not sure what extra modifications should I do on body of those methods.Actinopod
@Max: It looks like the default renderer for JFreeChart.createXYBarChart, XYBarRenderer, is not happy. Does setShadowVisible(false) help?Styria
A
1

Thanks trashgod :D But I gave up on this approach. I need to get some work done over here ;) So in order to navigate on the graph I used a different dataset org.jfree.data.time.DynamicTimeSeriesCollection.

This class is aimed for real-time applications in which we have the ability to append new data and discard the oldest in a pretty fast way (depend on your input data). In summary, every time that someone scroll the bar I just need to change my underlying dataset, and that will fire a PlotChangeEvent which, in turn, gets passed on to the chart and results in a ChartChangeEvent being fired.

This chain of events is used to ensure that charts are automatically updated whenever a change is made to any component of the chart.

Once again, thank you very much

Actinopod answered 14/7, 2010 at 0:21 Comment(2)
Seems like a reasonable alternative, and cleaner than the demo; +1. BTW, you need to use the @ tag for anyone but you to see a response.Styria
@trashgod: I found a new alternative, see you.Actinopod

© 2022 - 2024 — McMap. All rights reserved.