Abnormal Behaviour of the Zoom In and Zoom Out Functionality of the JFreeChart?
Asked Answered
A

1

2

I have observed that the functionality of the "Zoom-In" and "Zoom-out" was implemented quite different than expected.Like for example when i do one step "Zoom-out" and then again after one step back of "Zoom-In". I couldn't see the Original graph again.

I don't see "Zoom-In" and "Zoom-out" functionality of JFreechart to be in the sync.

public class ChartPanelDemo {

    private static final String title = "Historical Data Graph";
    private ChartPanel chartPanel = createChart();
    private JButton ZoomX;
    private JButton ZoomY;
    private JButton Zoom;
    private JButton ZoomXOut;
    private JButton ZoomYOut;
    private JButton ZoomOut;
    private JButton originalGraph;
    private JButton xscaleInc;
    private JButton xscaleDec;
    private NumberAxis domainAxis;
    private NumberAxis rangeAxis;
    private int UNITS = 1;
    private static final int COUNT = 100;

    private JPanel panel;

    private double[][] sizeFr = { { TableLayout.FILL }, { TableLayout.FILL } };

    public ChartPanelDemo() {
        JFrame f = new JFrame(title);

        panel = new JPanel();
        f.setTitle(title);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new BorderLayout(0, 5));
        f.add(chartPanel, BorderLayout.CENTER);
        chartPanel.setMouseWheelEnabled(true); 
        // chartPanel.setHorizontalAxisTrace(true);
        // chartPanel.setVerticalAxisTrace(true);
        chartPanel.setZoomInFactor(0.9);
        chartPanel.setZoomOutFactor(0.9);

        JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(createTrace());
        panel.add(createDate());
        panel.add(createZoom());
        panel.add(createZoomOutX());
        panel.add(createZoomOutY());
        panel.add(createZoomOut());
        panel.add(toOriginalGraph());
        panel.add(AutoScaleDecXaxis());
        //panel.add(AutoScaleDecXaxis());
        f.add(panel, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }



    private JSpinner AutoScaleDecXaxis() {
        final JSpinner spinner = new JSpinner(
                new SpinnerNumberModel(UNITS, 1, COUNT, 1));
            spinner.addChangeListener(new ChangeListener() {

                @Override
                public void stateChanged(ChangeEvent e) {
                    JSpinner s = (JSpinner) e.getSource();
                    Number n = (Number) s.getValue();
                    domainAxis.setTickUnit(new NumberTickUnit(n.intValue()));
                }
            });
            return spinner;
    }

    private JButton toOriginalGraph() {
        originalGraph = new JButton(new AbstractAction("RestoreGraph") {

            @Override
            public void actionPerformed(ActionEvent e) {
                chartPanel.restoreAutoBounds();
            }

        });
        return originalGraph;
    }

    private JButton createZoomOut() {
        ZoomOut = new JButton(new AbstractAction("ZoomOut") {

            @Override
            public void actionPerformed(ActionEvent e) {
                ZoomOut.setActionCommand(chartPanel.ZOOM_OUT_BOTH_COMMAND);
                ZoomOut.addActionListener(chartPanel);

            }

        });
        return ZoomOut;
    }

    private JButton createZoomOutY() {
        ZoomYOut = new JButton(new AbstractAction("ZoomOutY") {

            @Override
            public void actionPerformed(ActionEvent e) {
                ZoomYOut.setActionCommand(chartPanel.ZOOM_OUT_RANGE_COMMAND);
                ZoomYOut.addActionListener(chartPanel);
            }

        });
        return ZoomYOut;
    }

    private JButton createZoomOutX() {
        ZoomXOut = new JButton(new AbstractAction("ZoomOutX") {
            @Override
            public void actionPerformed(ActionEvent e) {
                ZoomXOut.setActionCommand(chartPanel.ZOOM_OUT_DOMAIN_COMMAND);
                ZoomXOut.addActionListener(chartPanel);
            }
        });
        return ZoomXOut;
    }

    private JButton createTrace() {
        ZoomX = new JButton(new AbstractAction("ZoomInX") {

            @Override
            public void actionPerformed(ActionEvent e) {
                ZoomX.setActionCommand(chartPanel.ZOOM_IN_DOMAIN_COMMAND);
                ZoomX.addActionListener(chartPanel);
                // chartPanel.restoreAutoBounds();
            }
        });
        return ZoomX;
    }

    private JButton createDate() {
        ZoomY = new JButton(new AbstractAction("ZoomInY") {

            @Override
            public void actionPerformed(ActionEvent e) {
                ZoomY.setActionCommand(chartPanel.ZOOM_IN_RANGE_COMMAND);
                ZoomY.addActionListener(chartPanel);
            }
        });
        return ZoomY;
    }

    private JButton createZoom() {
        Zoom = new JButton(new AbstractAction("Zoom") {

            @Override
            public void actionPerformed(ActionEvent e) {
                Zoom.setActionCommand(chartPanel.ZOOM_IN_BOTH_COMMAND);
                Zoom.addActionListener(chartPanel);
            }
        });
        return Zoom;
    }

    private ChartPanel createChart() {
        XYDataset roiData = createDataset();
        JFreeChart chart = createChart(roiData);
        chart.setBackgroundPaint(new Color(0xBBBBDD));
        XYPlot plot = chart.getXYPlot();
        XYSplineRenderer r = new XYSplineRenderer(20);
        plot.setRenderer(r);
        r.setBaseShapesVisible(true);
        rangeAxis = (NumberAxis) plot.getRangeAxis();
        domainAxis = (NumberAxis) plot.getDomainAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        domainAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        return new ChartPanel(chart);
    }

    private JFreeChart createChart(XYDataset dataset) {
        JFreeChart chart = ChartFactory.createXYLineChart("Historical Data", // chart
                                                                                // title
                "X", // x axis label
                "Y", // y axis label
                dataset, // data
                PlotOrientation.VERTICAL, true, // include legend
                true, // tooltips
                false // urls
                );
        return chart;

    }

    private XYDataset createDataset() {
        XYSeries series1 = new XYSeries("First");
        series1.add(1.0, 1.0);
        series1.add(2.0, 4.0);
        series1.add(3.0, 3.0);
        series1.add(4.0, 5.0);
        series1.add(5.0, 5.0);
        series1.add(6.0, 7.0);
        series1.add(7.0, 7.0);
        series1.add(8.0, 8.0);
        XYSeries series2 = new XYSeries("Second");
        series2.add(1.0, 5.0);
        series2.add(2.0, 7.0);
        series2.add(3.0, 6.0);
        series2.add(4.0, 8.0);
        series2.add(5.0, 4.0);
        series2.add(6.0, 4.0);
        series2.add(7.0, 2.0);
        series2.add(8.0, 1.0);

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series1);
        dataset.addSeries(series2);

        return dataset;
    }


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

            @Override
            public void run() {
                ChartPanelDemo cpd = new ChartPanelDemo();
            }
        });
    }
}

Problem2: After two clicks on ZoomInX enter image description here

And again after two clicks on ZoomOutX(Which is the original graph) enter image description here

But Again after two clicks on ZoomInX I see the graph a different one, not as the first image in this question which should be. enter image description here

Altitude answered 8/1, 2017 at 4:12 Comment(1)
I have updated the question with the sample code i tried with.Altitude
L
4

Your example appears to be mixing the two approaches suggested here, invoking the chart panel's handler from within your own actionPerformed() implementation. While the chart panel handlers are reusable, they are not re-entrant. Instead, use the chart panel's implementation directly. The example below focuses on two buttons to zoom the domain in and out:

toolBar.add(createButton("Zoom In X", ZOOM_IN_DOMAIN_COMMAND));
toolBar.add(createButton("Zoom Out X", ZOOM_OUT_DOMAIN_COMMAND));
…
private JButton createButton(String name, String command) {
    final JButton b = new JButton(name);
    b.setActionCommand(command);
    b.addActionListener(chartPanel);
    return b;
}

After clicking Zoom In X:

after zoom in x

After clicking Zoom Out X:

after zoom out x

This complete example re-factors the createButton() method to exercise the available zoom handlers and illustrates using a JToolBar.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
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.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.Year;
import org.jfree.data.xy.XYDataset;
import static org.jfree.chart.ChartPanel.*;

/** @see https://mcmap.net/q/541226/-zoom-in-and-zoom-out-functionality-on-a-button-click-on-jfreechart-line-graph */
public class ZoomDemo {

    private static final String TITLE = "Return On Investment";
    private final ChartPanel chartPanel = createChart();

    public ZoomDemo() {
        JFrame f = new JFrame(TITLE);
        f.setTitle(TITLE);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new BorderLayout(0, 5));
        f.add(chartPanel, BorderLayout.CENTER);
        chartPanel.setMouseWheelEnabled(true);

        JPanel panel = new JPanel();
        JToolBar toolBar = new JToolBar();
        toolBar.add(createButton("Zoom In", ZOOM_IN_BOTH_COMMAND));
        toolBar.add(createButton("Zoom In X", ZOOM_IN_DOMAIN_COMMAND));
        toolBar.add(createButton("Zoom In Y", ZOOM_IN_RANGE_COMMAND));
        toolBar.add(createButton("Zoom Out", ZOOM_OUT_BOTH_COMMAND));
        toolBar.add(createButton("Zoom Out X", ZOOM_OUT_DOMAIN_COMMAND));
        toolBar.add(createButton("Zoom Out Y", ZOOM_OUT_RANGE_COMMAND));
        toolBar.add(createButton("Reset", ZOOM_RESET_BOTH_COMMAND));
        toolBar.add(createButton("Reset X", ZOOM_RESET_DOMAIN_COMMAND));
        toolBar.add(createButton("Reset Y", ZOOM_RESET_RANGE_COMMAND));
        panel.add(toolBar);
        f.add(panel, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private JButton createButton(String name, String command) {
        final JButton b = new JButton(name);
        b.setActionCommand(command);
        b.addActionListener(chartPanel);
        return b;
    }

    private ChartPanel createChart() {
        XYDataset roiData = createDataset();
        JFreeChart chart = ChartFactory.createTimeSeriesChart(
            TITLE, "Date", "Value", roiData, true, true, false);
        XYPlot plot = chart.getXYPlot();
        XYLineAndShapeRenderer renderer =
            (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setBaseShapesVisible(true);
        NumberFormat currency = NumberFormat.getCurrencyInstance();
        currency.setMaximumFractionDigits(0);
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setNumberFormatOverride(currency);
        return new ChartPanel(chart);
    }

    private XYDataset createDataset() {
        TimeSeriesCollection tsc = new TimeSeriesCollection();
        tsc.addSeries(createSeries("Projected", 200));
        tsc.addSeries(createSeries("Actual", 100));
        return tsc;
    }

    private TimeSeries createSeries(String name, double scale) {
        TimeSeries series = new TimeSeries(name);
        for (int i = 0; i < 6; i++) {
            series.add(new Year(2016 + i), Math.pow(2, i) * scale);
        }
        return series;
    }

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

            @Override
            public void run() {
                ZoomDemo cpd = new ZoomDemo();
            }
        });
    }
}
Laryngology answered 9/1, 2017 at 8:42 Comment(4)
Have you tried my example? If you have taken my example buttons are not working on first click. and also i see strange behavior of Zoomin and ZoomOut functionality which was my question. but when i removed this two lines of code chartPanel.setZoomInFactor(0.9); chartPanel.setZoomOutFactor(0.9); ZoomIn and ZoomOut functionality is working fine as expected, but still with some problems which i explained in my question with title problem2.Altitude
Yes, I noticed that; the chart panel handlers are reusable but not re-entrant. My example focuses on the error seen in yours. Try updating your handlers as I've shown.Laryngology
any clue for this newer question posted?#41712118Altitude
any clue to this question on how to proceed ?#41999340Altitude

© 2022 - 2024 — McMap. All rights reserved.