CombinedDomainXYPlot not rescaling domain axis

后端 未结 2 1797
迷失自我
迷失自我 2020-11-22 11:05

When I hide number of series from a chart that is using a CombinedDomainXYPlot, all range axes are auto rescaled nicely. Howver, the domain axis does not get rescaled. Is th

相关标签:
2条回答
  • 2020-11-22 11:16

    ANSWERING MY OWN QUESTION:

    I managed to refresh the axis using a little hack:

     mainPlot.getDomainAxis().setAutoRange(false);
     mainPlot.getDomainAxis().setAutoRange(true);
    

    It is not nice but it does the trick. Nevertheless, I wish someone could post a nicer solution...

    Here is the code using non-custom data set that does not work. Please run it and then click on a big button called click multiple times to hide a few series. The domain axis is not rescaled.

    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.List;
    import java.util.Random;
    import javax.swing.*;
    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.event.ChartChangeEvent;
    import org.jfree.chart.event.ChartChangeListener;
    import org.jfree.chart.plot.CombinedDomainXYPlot;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
    import org.jfree.chart.renderer.xy.XYItemRenderer;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.xy.XYSeriesCollection;
    import org.jfree.ui.RectangleEdge;
    
    public class Runner {
    
        private static Random rand = new Random();
    
        public static void main(String[] args) {
            XYSeriesCollection data = new XYSeriesCollection();
            int max = rand.nextInt(2) + 2;
            for (int i = 0; i < max; i++) {
                data.addSeries(generateSeries("Series" + (i + 1)));
            }
            final XYItemRenderer renderer1 = new StandardXYItemRenderer();
            final XYPlot plot1 = new XYPlot(data, null, new DateAxis("Dates"), renderer1);
    
            data = new XYSeriesCollection();
            for (int i = 0; i < max; i++) {
                data.addSeries(generateSeries("Series" + (i + 1)));
            }
            final XYPlot plot2 = new XYPlot(data, null, new NumberAxis("Numbers"), renderer1);
    
            final CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain"));
            plot.setGap(10.0);
    
            // add the subplots...
            plot.add(plot1, 1);
            plot.add(plot2, 1);
            plot.setOrientation(PlotOrientation.VERTICAL);
    
            // return a new chart containing the overlaid plot...
            final JFreeChart chart = new JFreeChart("CombinedDomainXYPlot Demo",
                JFreeChart.DEFAULT_TITLE_FONT, plot, true);
            chart.getLegend().setPosition(RectangleEdge.RIGHT);
    
            chart.addChangeListener(new ChartChangeListener() {
    
                boolean changed = false;
    
                @Override
                public void chartChanged(ChartChangeEvent event) {
                    if (!changed) {
                    } else {
                        changed = false;
                    }
                }
            });
    
            ChartPanel panel = new ChartPanel(chart);
            JPanel panel2 = new JPanel(new BorderLayout(0, 10));
            panel2.add(panel, BorderLayout.CENTER);
            JButton b = new JButton("Click");
            b.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    CombinedDomainXYPlot plot = (CombinedDomainXYPlot) chart.getXYPlot();
                    List l = plot.getSubplots();
                    int index = rand.nextInt(plot1.getSeriesCount() + plot2.getSeriesCount());
                    boolean b = renderer1.isSeriesVisible(index);
                    renderer1.setSeriesVisible(index, false);
                }
            });
            panel2.add(b, BorderLayout.NORTH);
            panel2.setVisible(true);
    
            JFrame frame = new JFrame("dsadsa");
            frame.add(panel2);
            frame.setSize(800, 600);
            frame.setVisible(true);
        }
    
        private static XYSeries generateSeries(String key) {
            XYSeries series = new XYSeries(key);
            int points = 15;
            double val = 0.0;
            double x = 0.0;
            for (int i = 0; i < points; i++) {
                val += rand.nextDouble() * 6 - 3;
                x += rand.nextDouble() * 4;
                series.add(x, val);
            }
            return series;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 11:32

    CombinedDomainXYPlot establishes the combined maximal Range for its shared domain axis in getDataRange(). This is required to allow the axis to be shared. Changing the visibility of a series has no effect on the shared domain axis; changing the Dataset updates the shared domain axis via its configure() method. In either case, the subplots' range axes can be updated indepedently.

    The example below allows one to update a subplot or change a series' visibility independently. Break on configure() to see the effect. Your suggestion to toggle setAutoRange () can be replaced with a single call to configure(); but the effect should be nil, as the data and its combined maximal Range are unchanged.

    mainPlot.getDomainAxis().configure();
    

    To automatically update the shared domain axis, use addSeries() or removeSeries() instead of setSeriesVisible().

    As an aside, don't neglect Initial Threads and pack().

    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.util.Random;
    import javax.swing.*;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.axis.NumberAxis;
    import org.jfree.chart.plot.CombinedDomainXYPlot;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
    import static org.jfree.chart.renderer.xy.StandardXYItemRenderer.*;
    import org.jfree.chart.renderer.xy.XYItemRenderer;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.xy.XYSeriesCollection;
    
    /**
     * @see https://stackoverflow.com/a/64508866/230513
     * @see https://stackoverflow.com/q/11870416/230513
     */
    public class CombinedPlot {
    
        private static final int MAX = 3;
        private static final Random RND = new Random();
    
        public static void main(String[] args) {
            EventQueue.invokeLater(CombinedPlot::init);
        }
    
        private static void init() {
            XYItemRenderer renderer = new StandardXYItemRenderer(SHAPES_AND_LINES);
            XYPlot plot1 = new XYPlot(
                generateData(), null, new NumberAxis("Range 1"), renderer);
            XYPlot plot2 = new XYPlot(
                generateData(), null, new NumberAxis("Range 2"), renderer);
            final CombinedDomainXYPlot plot =
                new CombinedDomainXYPlot(new NumberAxis("Domain"));
            plot.setDomainPannable(true);
            plot.setRangePannable(true);
            plot.add(plot1);
            plot.add(plot2);
            plot.setOrientation(PlotOrientation.VERTICAL);
            JFreeChart chart = new JFreeChart(
                "Combined Plots", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
            ChartPanel chartPanel = new ChartPanel(chart);
            chartPanel.setPreferredSize(new Dimension(800, 500));
    
            JPanel controlPanel = new JPanel();
            controlPanel.add(new JButton(new UpdateAction(plot, 0)));
            controlPanel.add(new JButton(new UpdateAction(plot, 1)));
            for (int i = 0; i < MAX; i++) {
                JCheckBox jcb = new JCheckBox(new VisibleAction(renderer, i));
                jcb.setSelected(true);
                renderer.setSeriesVisible(i, true);
                controlPanel.add(jcb);
            }
    
            JFrame frame = new JFrame("Combined Plot Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(chartPanel, BorderLayout.CENTER);
            frame.add(controlPanel, BorderLayout.SOUTH);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        private static class UpdateAction extends AbstractAction {
    
            private final XYPlot plot;
    
            public UpdateAction(CombinedDomainXYPlot plot, int i) {
                super("Update plot " + (i + 1));
                this.plot = (XYPlot) plot.getSubplots().get(i);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                plot.setDataset(CombinedPlot.generateData());
            }
        }
    
        private static class VisibleAction extends AbstractAction {
    
            private XYItemRenderer renderer;
            private int i;
    
            public VisibleAction(XYItemRenderer renderer, int i) {
                super("Series " + (i + 1));
                this.renderer = renderer;
                this.i = i;
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                renderer.setSeriesVisible(i, !renderer.getSeriesVisible(i));
            }
        }
    
        private static XYSeriesCollection generateData() {
            XYSeriesCollection data = new XYSeriesCollection();
            for (int i = 0; i < MAX; i++) {
                data.addSeries(generateSeries("Series " + (i + 1)));
            }
            return data;
        }
    
        private static XYSeries generateSeries(String key) {
            XYSeries series = new XYSeries(key);
            for (int i = 0; i < 16; i++) {
                series.add(RND.nextGaussian(), RND.nextGaussian());
            }
            return series;
        }
    }
    
    0 讨论(0)
提交回复
热议问题